@rufous/ui 0.3.0 → 0.3.1
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/dist/main.cjs +53 -31
- package/dist/main.css +17 -0
- package/dist/main.d.cts +12 -0
- package/dist/main.d.ts +12 -0
- package/dist/main.js +53 -31
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -2252,10 +2252,12 @@ function AutocompleteInner(props, _ref) {
|
|
|
2252
2252
|
className = "",
|
|
2253
2253
|
style,
|
|
2254
2254
|
sx,
|
|
2255
|
+
open: openProp,
|
|
2255
2256
|
onOpen,
|
|
2256
2257
|
onClose
|
|
2257
2258
|
} = props;
|
|
2258
|
-
const [
|
|
2259
|
+
const [internalOpen, setInternalOpen] = (0, import_react19.useState)(false);
|
|
2260
|
+
const open = openProp !== void 0 ? openProp : internalOpen;
|
|
2259
2261
|
const [inputStr, setInputStr] = (0, import_react19.useState)("");
|
|
2260
2262
|
const [filterQuery, setFilterQuery] = (0, import_react19.useState)("");
|
|
2261
2263
|
const [focusedIdx, setFocusedIdx] = (0, import_react19.useState)(-1);
|
|
@@ -2341,20 +2343,20 @@ function AutocompleteInner(props, _ref) {
|
|
|
2341
2343
|
const openPopup = (0, import_react19.useCallback)(() => {
|
|
2342
2344
|
if (disabled) return;
|
|
2343
2345
|
calcPopupStyle();
|
|
2344
|
-
|
|
2346
|
+
if (openProp === void 0) setInternalOpen(true);
|
|
2345
2347
|
setFocusedIdx(-1);
|
|
2346
2348
|
setFilterQuery("");
|
|
2347
2349
|
onOpen?.();
|
|
2348
|
-
}, [disabled, calcPopupStyle, onOpen]);
|
|
2350
|
+
}, [disabled, calcPopupStyle, onOpen, openProp]);
|
|
2349
2351
|
const closePopup = (0, import_react19.useCallback)((justSelected = false) => {
|
|
2350
|
-
|
|
2352
|
+
if (openProp === void 0) setInternalOpen(false);
|
|
2351
2353
|
setFocusedIdx(-1);
|
|
2352
2354
|
onClose?.();
|
|
2353
2355
|
if (!justSelected && !freeSolo && !multiple && value == null) {
|
|
2354
2356
|
setInputStr("");
|
|
2355
2357
|
onInputChange?.(null, "");
|
|
2356
2358
|
}
|
|
2357
|
-
}, [freeSolo, multiple, value, onInputChange, onClose]);
|
|
2359
|
+
}, [openProp, freeSolo, multiple, value, onInputChange, onClose]);
|
|
2358
2360
|
(0, import_react19.useEffect)(() => {
|
|
2359
2361
|
if (!open) return;
|
|
2360
2362
|
const handleOutside = (e) => {
|
|
@@ -5133,6 +5135,7 @@ var Select = import_react24.default.forwardRef(function Select2(props, ref) {
|
|
|
5133
5135
|
disabled = false,
|
|
5134
5136
|
required = false,
|
|
5135
5137
|
multiple = false,
|
|
5138
|
+
groupBy,
|
|
5136
5139
|
className = "",
|
|
5137
5140
|
style,
|
|
5138
5141
|
sx
|
|
@@ -5312,32 +5315,51 @@ var Select = import_react24.default.forwardRef(function Select2(props, ref) {
|
|
|
5312
5315
|
),
|
|
5313
5316
|
helperText && /* @__PURE__ */ import_react24.default.createElement("div", { className: `rf-text-field__helper-text${error ? " rf-text-field__helper-text--error" : ""}` }, helperText),
|
|
5314
5317
|
open && !disabled && import_react_dom5.default.createPortal(
|
|
5315
|
-
/* @__PURE__ */ import_react24.default.createElement("div", { ref: popupRef, className: "rf-select__popup", role: "presentation", style: popupStyle }, /* @__PURE__ */ import_react24.default.createElement("ul", { ref: listRef, className: "rf-select__listbox", role: "listbox", "aria-multiselectable": multiple },
|
|
5316
|
-
const
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
|
|
5318
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { ref: popupRef, className: "rf-select__popup", role: "presentation", style: popupStyle }, /* @__PURE__ */ import_react24.default.createElement("ul", { ref: listRef, className: "rf-select__listbox", role: "listbox", "aria-multiselectable": multiple }, (() => {
|
|
5319
|
+
const renderOpt = (opt, selectableIdx) => {
|
|
5320
|
+
const selected = isSelected(opt.value);
|
|
5321
|
+
const focused = focusedIdx === selectableIdx;
|
|
5322
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
5323
|
+
"li",
|
|
5324
|
+
{
|
|
5325
|
+
key: opt.value,
|
|
5326
|
+
"data-idx": selectableIdx,
|
|
5327
|
+
role: "option",
|
|
5328
|
+
"aria-selected": selected,
|
|
5329
|
+
"aria-disabled": opt.disabled,
|
|
5330
|
+
className: [
|
|
5331
|
+
"rf-select__option",
|
|
5332
|
+
selected ? "rf-select__option--selected" : "",
|
|
5333
|
+
focused ? "rf-select__option--focused" : "",
|
|
5334
|
+
opt.disabled ? "rf-select__option--disabled" : ""
|
|
5335
|
+
].filter(Boolean).join(" "),
|
|
5336
|
+
onMouseEnter: () => setFocusedIdx(selectableIdx),
|
|
5337
|
+
onMouseLeave: () => setFocusedIdx(-1),
|
|
5338
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
5339
|
+
onClick: (e) => selectOption(opt, e)
|
|
5340
|
+
},
|
|
5341
|
+
/* @__PURE__ */ import_react24.default.createElement("span", { className: "rf-select__option-label" }, opt.label),
|
|
5342
|
+
/* @__PURE__ */ import_react24.default.createElement("span", { className: "rf-select__option-check", "aria-hidden": "true" }, /* @__PURE__ */ import_react24.default.createElement(CheckIcon2, null))
|
|
5343
|
+
);
|
|
5344
|
+
};
|
|
5345
|
+
let sCounter = 0;
|
|
5346
|
+
const selectableIdxMap = /* @__PURE__ */ new Map();
|
|
5347
|
+
options.forEach((o) => {
|
|
5348
|
+
if (!o.disabled) selectableIdxMap.set(o, sCounter++);
|
|
5349
|
+
});
|
|
5350
|
+
const resolveGroup = groupBy ? groupBy : (o) => o.group ?? "";
|
|
5351
|
+
const hasGroups = groupBy != null || options.some((o) => o.group != null);
|
|
5352
|
+
if (!hasGroups) {
|
|
5353
|
+
return options.map((opt) => renderOpt(opt, selectableIdxMap.get(opt) ?? -1));
|
|
5354
|
+
}
|
|
5355
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
5356
|
+
options.forEach((opt) => {
|
|
5357
|
+
const g = resolveGroup(opt);
|
|
5358
|
+
if (!groupMap.has(g)) groupMap.set(g, []);
|
|
5359
|
+
groupMap.get(g).push(opt);
|
|
5360
|
+
});
|
|
5361
|
+
return Array.from(groupMap.entries()).map(([groupName, groupOpts]) => /* @__PURE__ */ import_react24.default.createElement("li", { key: groupName, role: "presentation" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "rf-select__group-header" }, groupName), /* @__PURE__ */ import_react24.default.createElement("ul", { className: "rf-select__group-items", role: "group" }, groupOpts.map((opt) => renderOpt(opt, selectableIdxMap.get(opt) ?? -1)))));
|
|
5362
|
+
})())),
|
|
5341
5363
|
document.body
|
|
5342
5364
|
)
|
|
5343
5365
|
);
|
package/dist/main.css
CHANGED
|
@@ -2727,6 +2727,23 @@ pre {
|
|
|
2727
2727
|
.rf-select__option--selected .rf-select__option-check {
|
|
2728
2728
|
opacity: 1;
|
|
2729
2729
|
}
|
|
2730
|
+
.rf-select__group-header {
|
|
2731
|
+
padding: 6px 16px 4px;
|
|
2732
|
+
font-size: 0.7rem;
|
|
2733
|
+
font-weight: 700;
|
|
2734
|
+
letter-spacing: 0.07em;
|
|
2735
|
+
text-transform: uppercase;
|
|
2736
|
+
color: var(--primary-color, #a41b06);
|
|
2737
|
+
background: #fff5f5;
|
|
2738
|
+
position: sticky;
|
|
2739
|
+
top: 0;
|
|
2740
|
+
z-index: 1;
|
|
2741
|
+
}
|
|
2742
|
+
.rf-select__group-items {
|
|
2743
|
+
padding: 0;
|
|
2744
|
+
list-style: none;
|
|
2745
|
+
margin: 0;
|
|
2746
|
+
}
|
|
2730
2747
|
|
|
2731
2748
|
/* lib/styles/slider.css */
|
|
2732
2749
|
.rf-slider {
|
package/dist/main.d.cts
CHANGED
|
@@ -762,6 +762,15 @@ interface AutocompleteProps<T = string> {
|
|
|
762
762
|
style?: CSSProperties;
|
|
763
763
|
/** Scoped style overrides. Supports nested CSS selectors with & */
|
|
764
764
|
sx?: SxProp;
|
|
765
|
+
/**
|
|
766
|
+
* Controlled open state. When provided the dropdown respects this value.
|
|
767
|
+
* Pair with `onOpen` and `onClose` to sync your own state:
|
|
768
|
+
* ```
|
|
769
|
+
* const [open, setOpen] = useState(false);
|
|
770
|
+
* <Autocomplete open={open} onOpen={() => setOpen(true)} onClose={() => setOpen(false)} />
|
|
771
|
+
* ```
|
|
772
|
+
*/
|
|
773
|
+
open?: boolean;
|
|
765
774
|
/** Called when the popup opens */
|
|
766
775
|
onOpen?: () => void;
|
|
767
776
|
/** Called when the popup closes */
|
|
@@ -919,6 +928,7 @@ type SelectOption = {
|
|
|
919
928
|
value: string | number;
|
|
920
929
|
label: string;
|
|
921
930
|
disabled?: boolean;
|
|
931
|
+
group?: string;
|
|
922
932
|
};
|
|
923
933
|
interface SelectProps {
|
|
924
934
|
options: SelectOption[] | string[];
|
|
@@ -934,6 +944,8 @@ interface SelectProps {
|
|
|
934
944
|
disabled?: boolean;
|
|
935
945
|
required?: boolean;
|
|
936
946
|
multiple?: boolean;
|
|
947
|
+
/** Group options by returning a category string */
|
|
948
|
+
groupBy?: (option: SelectOption) => string;
|
|
937
949
|
className?: string;
|
|
938
950
|
style?: CSSProperties;
|
|
939
951
|
sx?: SxProp;
|
package/dist/main.d.ts
CHANGED
|
@@ -762,6 +762,15 @@ interface AutocompleteProps<T = string> {
|
|
|
762
762
|
style?: CSSProperties;
|
|
763
763
|
/** Scoped style overrides. Supports nested CSS selectors with & */
|
|
764
764
|
sx?: SxProp;
|
|
765
|
+
/**
|
|
766
|
+
* Controlled open state. When provided the dropdown respects this value.
|
|
767
|
+
* Pair with `onOpen` and `onClose` to sync your own state:
|
|
768
|
+
* ```
|
|
769
|
+
* const [open, setOpen] = useState(false);
|
|
770
|
+
* <Autocomplete open={open} onOpen={() => setOpen(true)} onClose={() => setOpen(false)} />
|
|
771
|
+
* ```
|
|
772
|
+
*/
|
|
773
|
+
open?: boolean;
|
|
765
774
|
/** Called when the popup opens */
|
|
766
775
|
onOpen?: () => void;
|
|
767
776
|
/** Called when the popup closes */
|
|
@@ -919,6 +928,7 @@ type SelectOption = {
|
|
|
919
928
|
value: string | number;
|
|
920
929
|
label: string;
|
|
921
930
|
disabled?: boolean;
|
|
931
|
+
group?: string;
|
|
922
932
|
};
|
|
923
933
|
interface SelectProps {
|
|
924
934
|
options: SelectOption[] | string[];
|
|
@@ -934,6 +944,8 @@ interface SelectProps {
|
|
|
934
944
|
disabled?: boolean;
|
|
935
945
|
required?: boolean;
|
|
936
946
|
multiple?: boolean;
|
|
947
|
+
/** Group options by returning a category string */
|
|
948
|
+
groupBy?: (option: SelectOption) => string;
|
|
937
949
|
className?: string;
|
|
938
950
|
style?: CSSProperties;
|
|
939
951
|
sx?: SxProp;
|
package/dist/main.js
CHANGED
|
@@ -2098,10 +2098,12 @@ function AutocompleteInner(props, _ref) {
|
|
|
2098
2098
|
className = "",
|
|
2099
2099
|
style,
|
|
2100
2100
|
sx,
|
|
2101
|
+
open: openProp,
|
|
2101
2102
|
onOpen,
|
|
2102
2103
|
onClose
|
|
2103
2104
|
} = props;
|
|
2104
|
-
const [
|
|
2105
|
+
const [internalOpen, setInternalOpen] = useState5(false);
|
|
2106
|
+
const open = openProp !== void 0 ? openProp : internalOpen;
|
|
2105
2107
|
const [inputStr, setInputStr] = useState5("");
|
|
2106
2108
|
const [filterQuery, setFilterQuery] = useState5("");
|
|
2107
2109
|
const [focusedIdx, setFocusedIdx] = useState5(-1);
|
|
@@ -2187,20 +2189,20 @@ function AutocompleteInner(props, _ref) {
|
|
|
2187
2189
|
const openPopup = useCallback2(() => {
|
|
2188
2190
|
if (disabled) return;
|
|
2189
2191
|
calcPopupStyle();
|
|
2190
|
-
|
|
2192
|
+
if (openProp === void 0) setInternalOpen(true);
|
|
2191
2193
|
setFocusedIdx(-1);
|
|
2192
2194
|
setFilterQuery("");
|
|
2193
2195
|
onOpen?.();
|
|
2194
|
-
}, [disabled, calcPopupStyle, onOpen]);
|
|
2196
|
+
}, [disabled, calcPopupStyle, onOpen, openProp]);
|
|
2195
2197
|
const closePopup = useCallback2((justSelected = false) => {
|
|
2196
|
-
|
|
2198
|
+
if (openProp === void 0) setInternalOpen(false);
|
|
2197
2199
|
setFocusedIdx(-1);
|
|
2198
2200
|
onClose?.();
|
|
2199
2201
|
if (!justSelected && !freeSolo && !multiple && value == null) {
|
|
2200
2202
|
setInputStr("");
|
|
2201
2203
|
onInputChange?.(null, "");
|
|
2202
2204
|
}
|
|
2203
|
-
}, [freeSolo, multiple, value, onInputChange, onClose]);
|
|
2205
|
+
}, [openProp, freeSolo, multiple, value, onInputChange, onClose]);
|
|
2204
2206
|
useEffect5(() => {
|
|
2205
2207
|
if (!open) return;
|
|
2206
2208
|
const handleOutside = (e) => {
|
|
@@ -5010,6 +5012,7 @@ var Select = React76.forwardRef(function Select2(props, ref) {
|
|
|
5010
5012
|
disabled = false,
|
|
5011
5013
|
required = false,
|
|
5012
5014
|
multiple = false,
|
|
5015
|
+
groupBy,
|
|
5013
5016
|
className = "",
|
|
5014
5017
|
style,
|
|
5015
5018
|
sx
|
|
@@ -5189,32 +5192,51 @@ var Select = React76.forwardRef(function Select2(props, ref) {
|
|
|
5189
5192
|
),
|
|
5190
5193
|
helperText && /* @__PURE__ */ React76.createElement("div", { className: `rf-text-field__helper-text${error ? " rf-text-field__helper-text--error" : ""}` }, helperText),
|
|
5191
5194
|
open && !disabled && ReactDOM4.createPortal(
|
|
5192
|
-
/* @__PURE__ */ React76.createElement("div", { ref: popupRef, className: "rf-select__popup", role: "presentation", style: popupStyle }, /* @__PURE__ */ React76.createElement("ul", { ref: listRef, className: "rf-select__listbox", role: "listbox", "aria-multiselectable": multiple },
|
|
5193
|
-
const
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5195
|
+
/* @__PURE__ */ React76.createElement("div", { ref: popupRef, className: "rf-select__popup", role: "presentation", style: popupStyle }, /* @__PURE__ */ React76.createElement("ul", { ref: listRef, className: "rf-select__listbox", role: "listbox", "aria-multiselectable": multiple }, (() => {
|
|
5196
|
+
const renderOpt = (opt, selectableIdx) => {
|
|
5197
|
+
const selected = isSelected(opt.value);
|
|
5198
|
+
const focused = focusedIdx === selectableIdx;
|
|
5199
|
+
return /* @__PURE__ */ React76.createElement(
|
|
5200
|
+
"li",
|
|
5201
|
+
{
|
|
5202
|
+
key: opt.value,
|
|
5203
|
+
"data-idx": selectableIdx,
|
|
5204
|
+
role: "option",
|
|
5205
|
+
"aria-selected": selected,
|
|
5206
|
+
"aria-disabled": opt.disabled,
|
|
5207
|
+
className: [
|
|
5208
|
+
"rf-select__option",
|
|
5209
|
+
selected ? "rf-select__option--selected" : "",
|
|
5210
|
+
focused ? "rf-select__option--focused" : "",
|
|
5211
|
+
opt.disabled ? "rf-select__option--disabled" : ""
|
|
5212
|
+
].filter(Boolean).join(" "),
|
|
5213
|
+
onMouseEnter: () => setFocusedIdx(selectableIdx),
|
|
5214
|
+
onMouseLeave: () => setFocusedIdx(-1),
|
|
5215
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
5216
|
+
onClick: (e) => selectOption(opt, e)
|
|
5217
|
+
},
|
|
5218
|
+
/* @__PURE__ */ React76.createElement("span", { className: "rf-select__option-label" }, opt.label),
|
|
5219
|
+
/* @__PURE__ */ React76.createElement("span", { className: "rf-select__option-check", "aria-hidden": "true" }, /* @__PURE__ */ React76.createElement(CheckIcon2, null))
|
|
5220
|
+
);
|
|
5221
|
+
};
|
|
5222
|
+
let sCounter = 0;
|
|
5223
|
+
const selectableIdxMap = /* @__PURE__ */ new Map();
|
|
5224
|
+
options.forEach((o) => {
|
|
5225
|
+
if (!o.disabled) selectableIdxMap.set(o, sCounter++);
|
|
5226
|
+
});
|
|
5227
|
+
const resolveGroup = groupBy ? groupBy : (o) => o.group ?? "";
|
|
5228
|
+
const hasGroups = groupBy != null || options.some((o) => o.group != null);
|
|
5229
|
+
if (!hasGroups) {
|
|
5230
|
+
return options.map((opt) => renderOpt(opt, selectableIdxMap.get(opt) ?? -1));
|
|
5231
|
+
}
|
|
5232
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
5233
|
+
options.forEach((opt) => {
|
|
5234
|
+
const g = resolveGroup(opt);
|
|
5235
|
+
if (!groupMap.has(g)) groupMap.set(g, []);
|
|
5236
|
+
groupMap.get(g).push(opt);
|
|
5237
|
+
});
|
|
5238
|
+
return Array.from(groupMap.entries()).map(([groupName, groupOpts]) => /* @__PURE__ */ React76.createElement("li", { key: groupName, role: "presentation" }, /* @__PURE__ */ React76.createElement("div", { className: "rf-select__group-header" }, groupName), /* @__PURE__ */ React76.createElement("ul", { className: "rf-select__group-items", role: "group" }, groupOpts.map((opt) => renderOpt(opt, selectableIdxMap.get(opt) ?? -1)))));
|
|
5239
|
+
})())),
|
|
5218
5240
|
document.body
|
|
5219
5241
|
)
|
|
5220
5242
|
);
|