prime-ui-kit 0.7.4 → 0.7.7
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/components/index.css +326 -34
- package/dist/components/index.css.map +4 -4
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +811 -110
- package/dist/components/index.js.map +4 -4
- package/dist/components/select/Select.d.ts +26 -9
- package/dist/components/select/Select.d.ts.map +1 -1
- package/dist/components/select/examples/pattern-multiple.d.ts +3 -0
- package/dist/components/select/examples/pattern-multiple.d.ts.map +1 -0
- package/dist/components/tag-select/TagSelect.d.ts +43 -0
- package/dist/components/tag-select/TagSelect.d.ts.map +1 -0
- package/dist/components/tag-select/examples/pattern-canonical.d.ts +3 -0
- package/dist/components/tag-select/examples/pattern-canonical.d.ts.map +1 -0
- package/dist/components/tag-select/examples/pattern-features.d.ts +3 -0
- package/dist/components/tag-select/examples/pattern-features.d.ts.map +1 -0
- package/dist/hooks/usePosition.d.ts.map +1 -1
- package/dist/index.css +328 -36
- package/dist/index.css.map +4 -4
- package/dist/index.js +811 -110
- package/dist/index.js.map +4 -4
- package/dist/tokens/semantic.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/select/COMPONENT.md +91 -32
- package/src/components/select/examples/pattern-multiple.tsx +30 -0
- package/src/components/tag-select/COMPONENT.md +108 -0
- package/src/components/tag-select/examples/examples.module.css +14 -0
- package/src/components/tag-select/examples/pattern-canonical.tsx +28 -0
- package/src/components/tag-select/examples/pattern-features.tsx +32 -0
- package/src/styles/theme-dark.css +1 -1
- package/src/styles/theme-light.css +1 -1
package/dist/index.js
CHANGED
|
@@ -3832,11 +3832,15 @@ function usePosition(anchorRef, contentRef, options = {}) {
|
|
|
3832
3832
|
(pos) => {
|
|
3833
3833
|
const content = contentRef.current;
|
|
3834
3834
|
if (!content) return;
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
content.style.
|
|
3835
|
+
const nextTop = `${pos.top}px`;
|
|
3836
|
+
const nextLeft = `${pos.left}px`;
|
|
3837
|
+
const nextMinW = pos.minWidth !== void 0 ? `${pos.minWidth}px` : "";
|
|
3838
|
+
const nextMaxH = pos.maxHeight !== void 0 ? `${pos.maxHeight}px` : "";
|
|
3839
|
+
if (content.style.position !== pos.position) content.style.position = pos.position;
|
|
3840
|
+
if (content.style.top !== nextTop) content.style.top = nextTop;
|
|
3841
|
+
if (content.style.left !== nextLeft) content.style.left = nextLeft;
|
|
3842
|
+
if (content.style.minWidth !== nextMinW) content.style.minWidth = nextMinW;
|
|
3843
|
+
if (content.style.maxHeight !== nextMaxH) content.style.maxHeight = nextMaxH;
|
|
3840
3844
|
},
|
|
3841
3845
|
[contentRef]
|
|
3842
3846
|
);
|
|
@@ -3854,7 +3858,7 @@ function usePosition(anchorRef, contentRef, options = {}) {
|
|
|
3854
3858
|
window.innerHeight,
|
|
3855
3859
|
{ preferredSide, align, offset, viewportPad, flip, matchTriggerMinWidth }
|
|
3856
3860
|
);
|
|
3857
|
-
setResolvedSide(pos.resolvedSide);
|
|
3861
|
+
setResolvedSide((prev) => pos.resolvedSide === prev ? prev : pos.resolvedSide);
|
|
3858
3862
|
applyPositionStyle({
|
|
3859
3863
|
position: "fixed",
|
|
3860
3864
|
top: pos.top,
|
|
@@ -3877,6 +3881,21 @@ function usePosition(anchorRef, contentRef, options = {}) {
|
|
|
3877
3881
|
return { resolvedSide, update };
|
|
3878
3882
|
}
|
|
3879
3883
|
|
|
3884
|
+
// src/internal/scrollAncestors.ts
|
|
3885
|
+
var SCROLLABLE = /^(auto|scroll|overlay)$/;
|
|
3886
|
+
function getScrollContainers(node) {
|
|
3887
|
+
const out = [window];
|
|
3888
|
+
if (!node || typeof window === "undefined") return out;
|
|
3889
|
+
for (let el = node.parentElement; el; el = el.parentElement) {
|
|
3890
|
+
const { overflowX, overflowY } = window.getComputedStyle(el);
|
|
3891
|
+
if (SCROLLABLE.test(overflowY) || SCROLLABLE.test(overflowX)) {
|
|
3892
|
+
out.push(el);
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
if (window.visualViewport) out.push(window.visualViewport);
|
|
3896
|
+
return out;
|
|
3897
|
+
}
|
|
3898
|
+
|
|
3880
3899
|
// src/components/select/Select.module.css
|
|
3881
3900
|
var Select_default = {
|
|
3882
3901
|
trigger: "Select_trigger",
|
|
@@ -3958,13 +3977,22 @@ function handleSelectListboxKeyDown(e, ctx) {
|
|
|
3958
3977
|
|
|
3959
3978
|
// src/components/select/Select.tsx
|
|
3960
3979
|
import { jsx as jsx26, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3980
|
+
var SELECT_LISTBOX_POSITION_OPTS = {
|
|
3981
|
+
side: "bottom",
|
|
3982
|
+
align: "start"
|
|
3983
|
+
};
|
|
3961
3984
|
var [SelectProvider, useSelectContext] = createComponentContext("Select");
|
|
3962
3985
|
function SelectRoot(props) {
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3986
|
+
if (props.multiple === true) {
|
|
3987
|
+
if (props.native === true) {
|
|
3988
|
+
return /* @__PURE__ */ jsx26(SelectNativeMultiRoot, { ...props });
|
|
3989
|
+
}
|
|
3990
|
+
return /* @__PURE__ */ jsx26(SelectComboboxMultiRoot, { ...props });
|
|
3991
|
+
}
|
|
3992
|
+
if (props.native === true) {
|
|
3993
|
+
return /* @__PURE__ */ jsx26(SelectNativeRoot, { ...props });
|
|
3966
3994
|
}
|
|
3967
|
-
return /* @__PURE__ */ jsx26(SelectComboboxRoot, { ...
|
|
3995
|
+
return /* @__PURE__ */ jsx26(SelectComboboxRoot, { ...props });
|
|
3968
3996
|
}
|
|
3969
3997
|
SelectRoot.displayName = "SelectRoot";
|
|
3970
3998
|
function SelectComboboxRoot({
|
|
@@ -4012,32 +4040,138 @@ function SelectComboboxRoot({
|
|
|
4012
4040
|
);
|
|
4013
4041
|
const onClose = React38.useCallback(() => setIsOpen(false), []);
|
|
4014
4042
|
const onOpen = React38.useCallback(() => setIsOpen(true), []);
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4043
|
+
const contextValue = React38.useMemo(
|
|
4044
|
+
() => ({
|
|
4045
|
+
size,
|
|
4046
|
+
hasError,
|
|
4047
|
+
isOpen,
|
|
4048
|
+
multiple: false,
|
|
4049
|
+
selectedValue,
|
|
4050
|
+
selectedLabelBinding,
|
|
4051
|
+
selectedValues: [],
|
|
4052
|
+
labelsByValue: {},
|
|
4053
|
+
onSelect,
|
|
4054
|
+
onClose,
|
|
4055
|
+
onOpen,
|
|
4056
|
+
highlightedValue,
|
|
4057
|
+
setHighlightedValue,
|
|
4058
|
+
triggerId,
|
|
4059
|
+
listboxId,
|
|
4060
|
+
triggerRef,
|
|
4061
|
+
disabled,
|
|
4062
|
+
placeholder,
|
|
4063
|
+
onInitLabel
|
|
4064
|
+
}),
|
|
4065
|
+
[
|
|
4066
|
+
size,
|
|
4067
|
+
hasError,
|
|
4068
|
+
isOpen,
|
|
4069
|
+
selectedValue,
|
|
4070
|
+
selectedLabelBinding,
|
|
4071
|
+
onSelect,
|
|
4072
|
+
onClose,
|
|
4073
|
+
onOpen,
|
|
4074
|
+
highlightedValue,
|
|
4075
|
+
triggerId,
|
|
4076
|
+
listboxId,
|
|
4077
|
+
disabled,
|
|
4078
|
+
placeholder,
|
|
4079
|
+
onInitLabel
|
|
4080
|
+
]
|
|
4038
4081
|
);
|
|
4082
|
+
return /* @__PURE__ */ jsx26(SelectProvider, { value: contextValue, children: /* @__PURE__ */ jsx26(ControlSizeProvider, { value: size, children }) });
|
|
4039
4083
|
}
|
|
4040
4084
|
SelectComboboxRoot.displayName = "SelectComboboxRoot";
|
|
4085
|
+
function SelectComboboxMultiRoot({
|
|
4086
|
+
size = "m",
|
|
4087
|
+
value,
|
|
4088
|
+
defaultValue,
|
|
4089
|
+
onChange,
|
|
4090
|
+
disabled,
|
|
4091
|
+
placeholder,
|
|
4092
|
+
hasError = false,
|
|
4093
|
+
children
|
|
4094
|
+
}) {
|
|
4095
|
+
const handleChange = React38.useCallback(
|
|
4096
|
+
(next) => {
|
|
4097
|
+
onChange?.(next);
|
|
4098
|
+
},
|
|
4099
|
+
[onChange]
|
|
4100
|
+
);
|
|
4101
|
+
const [selectedValues, setSelectedValues] = useControllableState({
|
|
4102
|
+
value,
|
|
4103
|
+
defaultValue: defaultValue ?? [],
|
|
4104
|
+
onChange: handleChange
|
|
4105
|
+
});
|
|
4106
|
+
const [labelsByValue, setLabelsByValue] = React38.useState({});
|
|
4107
|
+
const [isOpen, setIsOpen] = React38.useState(false);
|
|
4108
|
+
const [highlightedValue, setHighlightedValue] = React38.useState(void 0);
|
|
4109
|
+
const generatedId = React38.useId();
|
|
4110
|
+
const triggerId = `${generatedId}-trigger`;
|
|
4111
|
+
const listboxId = `${generatedId}-listbox`;
|
|
4112
|
+
const triggerRef = React38.useRef(null);
|
|
4113
|
+
const onInitLabel = React38.useCallback((val, label) => {
|
|
4114
|
+
setLabelsByValue((prev) => {
|
|
4115
|
+
if (prev[val] === label) return prev;
|
|
4116
|
+
return { ...prev, [val]: label };
|
|
4117
|
+
});
|
|
4118
|
+
}, []);
|
|
4119
|
+
const onSelect = React38.useCallback(
|
|
4120
|
+
(val, label) => {
|
|
4121
|
+
setLabelsByValue((prev) => ({ ...prev, [val]: label }));
|
|
4122
|
+
setSelectedValues((prev) => {
|
|
4123
|
+
if (prev.includes(val)) {
|
|
4124
|
+
return prev.filter((x) => x !== val);
|
|
4125
|
+
}
|
|
4126
|
+
return [...prev, val];
|
|
4127
|
+
});
|
|
4128
|
+
},
|
|
4129
|
+
[setSelectedValues]
|
|
4130
|
+
);
|
|
4131
|
+
const onClose = React38.useCallback(() => setIsOpen(false), []);
|
|
4132
|
+
const onOpen = React38.useCallback(() => setIsOpen(true), []);
|
|
4133
|
+
const contextValue = React38.useMemo(
|
|
4134
|
+
() => ({
|
|
4135
|
+
size,
|
|
4136
|
+
hasError,
|
|
4137
|
+
isOpen,
|
|
4138
|
+
multiple: true,
|
|
4139
|
+
selectedValue: void 0,
|
|
4140
|
+
selectedLabelBinding: void 0,
|
|
4141
|
+
selectedValues,
|
|
4142
|
+
labelsByValue,
|
|
4143
|
+
onSelect,
|
|
4144
|
+
onClose,
|
|
4145
|
+
onOpen,
|
|
4146
|
+
highlightedValue,
|
|
4147
|
+
setHighlightedValue,
|
|
4148
|
+
triggerId,
|
|
4149
|
+
listboxId,
|
|
4150
|
+
triggerRef,
|
|
4151
|
+
disabled,
|
|
4152
|
+
placeholder,
|
|
4153
|
+
onInitLabel
|
|
4154
|
+
}),
|
|
4155
|
+
[
|
|
4156
|
+
size,
|
|
4157
|
+
hasError,
|
|
4158
|
+
isOpen,
|
|
4159
|
+
selectedValues,
|
|
4160
|
+
labelsByValue,
|
|
4161
|
+
onSelect,
|
|
4162
|
+
onClose,
|
|
4163
|
+
onOpen,
|
|
4164
|
+
highlightedValue,
|
|
4165
|
+
triggerId,
|
|
4166
|
+
listboxId,
|
|
4167
|
+
disabled,
|
|
4168
|
+
placeholder,
|
|
4169
|
+
onInitLabel
|
|
4170
|
+
]
|
|
4171
|
+
);
|
|
4172
|
+
return /* @__PURE__ */ jsx26(SelectProvider, { value: contextValue, children: /* @__PURE__ */ jsx26(ControlSizeProvider, { value: size, children }) });
|
|
4173
|
+
}
|
|
4174
|
+
SelectComboboxMultiRoot.displayName = "SelectComboboxMultiRoot";
|
|
4041
4175
|
var SelectTrigger = React38.forwardRef(
|
|
4042
4176
|
({ className, children, onClick, onKeyDown, ...rest }, forwardedRef) => {
|
|
4043
4177
|
const { isOpen, onOpen, onClose, triggerId, listboxId, disabled, size, hasError, triggerRef } = useSelectContext();
|
|
@@ -4092,7 +4226,20 @@ var SelectTrigger = React38.forwardRef(
|
|
|
4092
4226
|
);
|
|
4093
4227
|
SelectTrigger.displayName = "SelectTrigger";
|
|
4094
4228
|
function SelectValue({ className }) {
|
|
4095
|
-
const
|
|
4229
|
+
const ctx = useSelectContext();
|
|
4230
|
+
if (ctx.multiple) {
|
|
4231
|
+
const { selectedValues, labelsByValue, placeholder: placeholder2 } = ctx;
|
|
4232
|
+
const display2 = selectedValues.length === 0 ? placeholder2 : selectedValues.map((v) => labelsByValue[v] ?? v).join(", ");
|
|
4233
|
+
return /* @__PURE__ */ jsx26(
|
|
4234
|
+
"span",
|
|
4235
|
+
{
|
|
4236
|
+
className: cx(Select_default.triggerValue, className),
|
|
4237
|
+
...toDataAttributes({ placeholder: display2 == null || display2 === "" }),
|
|
4238
|
+
children: display2
|
|
4239
|
+
}
|
|
4240
|
+
);
|
|
4241
|
+
}
|
|
4242
|
+
const { selectedLabelBinding, selectedValue, placeholder } = ctx;
|
|
4096
4243
|
const display = selectedLabelBinding && selectedLabelBinding.value === selectedValue ? selectedLabelBinding.label : selectedValue ?? placeholder;
|
|
4097
4244
|
return /* @__PURE__ */ jsx26(
|
|
4098
4245
|
"span",
|
|
@@ -4119,67 +4266,109 @@ function SelectContent({ className, children }) {
|
|
|
4119
4266
|
highlightedValue,
|
|
4120
4267
|
setHighlightedValue,
|
|
4121
4268
|
selectedValue,
|
|
4269
|
+
selectedValues,
|
|
4270
|
+
multiple,
|
|
4122
4271
|
size
|
|
4123
4272
|
} = useSelectContext();
|
|
4273
|
+
const selectedValueRef = React38.useRef(selectedValue);
|
|
4274
|
+
selectedValueRef.current = selectedValue;
|
|
4275
|
+
const selectedValuesRef = React38.useRef(selectedValues);
|
|
4276
|
+
selectedValuesRef.current = selectedValues;
|
|
4277
|
+
const multipleRef = React38.useRef(multiple);
|
|
4278
|
+
multipleRef.current = multiple;
|
|
4124
4279
|
const overlayPortalLayer = useOverlayPortalLayer();
|
|
4125
4280
|
const contentRef = React38.useRef(null);
|
|
4126
|
-
const { resolvedSide, update } = usePosition(
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4281
|
+
const { resolvedSide, update } = usePosition(
|
|
4282
|
+
triggerRef,
|
|
4283
|
+
contentRef,
|
|
4284
|
+
SELECT_LISTBOX_POSITION_OPTS
|
|
4285
|
+
);
|
|
4286
|
+
const updateRef = React38.useRef(update);
|
|
4287
|
+
updateRef.current = update;
|
|
4130
4288
|
const getItems = React38.useCallback(() => queryEnabledSelectOptions(contentRef.current), []);
|
|
4131
4289
|
React38.useLayoutEffect(() => {
|
|
4132
4290
|
if (!isOpen) return;
|
|
4133
|
-
|
|
4134
|
-
const rafId = requestAnimationFrame(() =>
|
|
4291
|
+
updateRef.current();
|
|
4292
|
+
const rafId = requestAnimationFrame(() => updateRef.current());
|
|
4135
4293
|
return () => cancelAnimationFrame(rafId);
|
|
4136
|
-
}, [isOpen
|
|
4294
|
+
}, [isOpen]);
|
|
4137
4295
|
React38.useEffect(() => {
|
|
4138
4296
|
if (!isOpen) {
|
|
4139
4297
|
setHighlightedValue(void 0);
|
|
4140
4298
|
return;
|
|
4141
4299
|
}
|
|
4142
|
-
const reposition = () => {
|
|
4143
|
-
requestAnimationFrame(() => update());
|
|
4144
|
-
};
|
|
4145
4300
|
const bootstrap = () => {
|
|
4146
4301
|
requestAnimationFrame(() => {
|
|
4147
4302
|
const el = contentRef.current;
|
|
4148
4303
|
if (!el) return;
|
|
4149
4304
|
el.focus({ preventScroll: true });
|
|
4150
4305
|
const items = queryEnabledSelectOptions(el);
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4306
|
+
if (multipleRef.current) {
|
|
4307
|
+
const sv = selectedValuesRef.current;
|
|
4308
|
+
const firstSelected = sv.find((v) => items.some((i) => i.dataset.value === v));
|
|
4309
|
+
setHighlightedValue(firstSelected ?? void 0);
|
|
4310
|
+
} else {
|
|
4311
|
+
const sv = selectedValueRef.current;
|
|
4312
|
+
const selectedIndex = items.findIndex((i) => i.dataset.value === sv);
|
|
4313
|
+
if (selectedIndex >= 0 && sv) {
|
|
4314
|
+
setHighlightedValue(sv);
|
|
4315
|
+
}
|
|
4154
4316
|
}
|
|
4155
4317
|
});
|
|
4156
4318
|
};
|
|
4157
4319
|
bootstrap();
|
|
4158
|
-
|
|
4320
|
+
}, [isOpen, setHighlightedValue]);
|
|
4321
|
+
React38.useEffect(() => {
|
|
4322
|
+
if (!isOpen) return;
|
|
4323
|
+
let rafCoalesce = 0;
|
|
4324
|
+
const schedule = () => {
|
|
4325
|
+
cancelAnimationFrame(rafCoalesce);
|
|
4326
|
+
rafCoalesce = requestAnimationFrame(() => updateRef.current());
|
|
4327
|
+
};
|
|
4328
|
+
window.addEventListener("resize", schedule);
|
|
4329
|
+
const scrollTargets = getScrollContainers(triggerRef.current);
|
|
4330
|
+
for (const t of scrollTargets) {
|
|
4331
|
+
t.addEventListener("scroll", schedule, { passive: true });
|
|
4332
|
+
}
|
|
4159
4333
|
const vv = window.visualViewport;
|
|
4160
|
-
vv?.addEventListener("resize",
|
|
4334
|
+
vv?.addEventListener("resize", schedule);
|
|
4335
|
+
const panel = contentRef.current;
|
|
4336
|
+
let ro = null;
|
|
4337
|
+
if (typeof ResizeObserver !== "undefined" && panel) {
|
|
4338
|
+
ro = new ResizeObserver(schedule);
|
|
4339
|
+
ro.observe(panel);
|
|
4340
|
+
}
|
|
4161
4341
|
return () => {
|
|
4162
|
-
|
|
4163
|
-
|
|
4342
|
+
cancelAnimationFrame(rafCoalesce);
|
|
4343
|
+
window.removeEventListener("resize", schedule);
|
|
4344
|
+
for (const t of scrollTargets) {
|
|
4345
|
+
t.removeEventListener("scroll", schedule);
|
|
4346
|
+
}
|
|
4347
|
+
vv?.removeEventListener("resize", schedule);
|
|
4348
|
+
ro?.disconnect();
|
|
4164
4349
|
};
|
|
4165
|
-
}, [isOpen,
|
|
4350
|
+
}, [isOpen, triggerRef]);
|
|
4166
4351
|
useEscapeKey({ enabled: isOpen, onEscape: onClose });
|
|
4167
4352
|
useOutsideClick({ refs: [triggerRef, contentRef], enabled: isOpen, onOutsideClick: onClose });
|
|
4168
|
-
const handleKeyDown = (
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4353
|
+
const handleKeyDown = React38.useCallback(
|
|
4354
|
+
(e) => {
|
|
4355
|
+
handleSelectListboxKeyDown(e, {
|
|
4356
|
+
items: getItems(),
|
|
4357
|
+
highlightedValue,
|
|
4358
|
+
setHighlightedValue,
|
|
4359
|
+
onSelect,
|
|
4360
|
+
onClose
|
|
4361
|
+
});
|
|
4362
|
+
},
|
|
4363
|
+
[getItems, highlightedValue, setHighlightedValue, onSelect, onClose]
|
|
4364
|
+
);
|
|
4177
4365
|
return /* @__PURE__ */ jsx26(Portal, { children: /* @__PURE__ */ jsx26(
|
|
4178
4366
|
ScrollContainer,
|
|
4179
4367
|
{
|
|
4180
4368
|
ref: contentRef,
|
|
4181
4369
|
id: listboxId,
|
|
4182
4370
|
role: "listbox",
|
|
4371
|
+
"aria-multiselectable": multiple ? true : void 0,
|
|
4183
4372
|
"aria-labelledby": triggerId,
|
|
4184
4373
|
"aria-hidden": !isOpen,
|
|
4185
4374
|
tabIndex: -1,
|
|
@@ -4198,6 +4387,17 @@ function SelectItemIcon({ className, children, ...rest }) {
|
|
|
4198
4387
|
return /* @__PURE__ */ jsx26("span", { className: cx(Select_default.itemIcon, className), ...rest, children });
|
|
4199
4388
|
}
|
|
4200
4389
|
SelectItemIcon.displayName = "SelectItemIcon";
|
|
4390
|
+
var SELECT_ITEM_ICON_MARKER = "__primeSelectItemIcon";
|
|
4391
|
+
Object.assign(SelectItemIcon, { [SELECT_ITEM_ICON_MARKER]: true });
|
|
4392
|
+
function isSelectItemIconType(type) {
|
|
4393
|
+
if (type === SelectItemIcon) return true;
|
|
4394
|
+
if (typeof type === "function") {
|
|
4395
|
+
const fn = type;
|
|
4396
|
+
if (fn[SELECT_ITEM_ICON_MARKER] === true) return true;
|
|
4397
|
+
if (fn.displayName === "SelectItemIcon") return true;
|
|
4398
|
+
}
|
|
4399
|
+
return false;
|
|
4400
|
+
}
|
|
4201
4401
|
function selectItemTextFromRest(rest) {
|
|
4202
4402
|
const parts = [];
|
|
4203
4403
|
for (const node of rest) {
|
|
@@ -4212,7 +4412,7 @@ function partitionSelectItemChildren(children) {
|
|
|
4212
4412
|
const icons = [];
|
|
4213
4413
|
const rest = [];
|
|
4214
4414
|
React38.Children.forEach(children, (child) => {
|
|
4215
|
-
if (React38.isValidElement(child) && child.type
|
|
4415
|
+
if (React38.isValidElement(child) && isSelectItemIconType(child.type)) {
|
|
4216
4416
|
icons.push(child);
|
|
4217
4417
|
} else if (child != null && child !== false) {
|
|
4218
4418
|
rest.push(child);
|
|
@@ -4222,9 +4422,18 @@ function partitionSelectItemChildren(children) {
|
|
|
4222
4422
|
}
|
|
4223
4423
|
var SelectItem = React38.forwardRef(
|
|
4224
4424
|
({ value, label, disabled, className, children }, ref) => {
|
|
4225
|
-
const {
|
|
4425
|
+
const {
|
|
4426
|
+
multiple,
|
|
4427
|
+
size,
|
|
4428
|
+
selectedValue,
|
|
4429
|
+
selectedValues,
|
|
4430
|
+
highlightedValue,
|
|
4431
|
+
setHighlightedValue,
|
|
4432
|
+
onSelect,
|
|
4433
|
+
onInitLabel
|
|
4434
|
+
} = useSelectContext();
|
|
4226
4435
|
const { icons, rest } = partitionSelectItemChildren(children);
|
|
4227
|
-
const isSelected = selectedValue === value;
|
|
4436
|
+
const isSelected = multiple ? selectedValues.includes(value) : selectedValue === value;
|
|
4228
4437
|
const isHighlighted = highlightedValue === value;
|
|
4229
4438
|
const resolvedLabel = label ?? selectItemTextFromRest(rest) ?? (typeof children === "string" ? children : void 0) ?? value;
|
|
4230
4439
|
React38.useEffect(() => {
|
|
@@ -4259,7 +4468,8 @@ var SelectItem = React38.forwardRef(
|
|
|
4259
4468
|
label: resolvedLabel,
|
|
4260
4469
|
selected: isSelected,
|
|
4261
4470
|
highlighted: isHighlighted,
|
|
4262
|
-
disabled: Boolean(disabled)
|
|
4471
|
+
disabled: Boolean(disabled),
|
|
4472
|
+
size
|
|
4263
4473
|
}),
|
|
4264
4474
|
children: [
|
|
4265
4475
|
icons.map(
|
|
@@ -4280,7 +4490,8 @@ function SelectGroup({ className, ...rest }) {
|
|
|
4280
4490
|
}
|
|
4281
4491
|
SelectGroup.displayName = "SelectGroup";
|
|
4282
4492
|
function SelectGroupLabel({ className, ...rest }) {
|
|
4283
|
-
|
|
4493
|
+
const { size } = useSelectContext();
|
|
4494
|
+
return /* @__PURE__ */ jsx26("div", { className: cx(Select_default.groupLabel, className), ...rest, ...toDataAttributes({ size }) });
|
|
4284
4495
|
}
|
|
4285
4496
|
SelectGroupLabel.displayName = "SelectGroupLabel";
|
|
4286
4497
|
function SelectSeparator({ className, ...rest }) {
|
|
@@ -4416,6 +4627,49 @@ function SelectNativeRoot({
|
|
|
4416
4627
|
) });
|
|
4417
4628
|
}
|
|
4418
4629
|
SelectNativeRoot.displayName = "SelectNativeRoot";
|
|
4630
|
+
function SelectNativeMultiRoot({
|
|
4631
|
+
size = "m",
|
|
4632
|
+
value,
|
|
4633
|
+
defaultValue,
|
|
4634
|
+
onChange,
|
|
4635
|
+
disabled,
|
|
4636
|
+
hasError = false,
|
|
4637
|
+
children
|
|
4638
|
+
}) {
|
|
4639
|
+
const handleChange = React38.useCallback(
|
|
4640
|
+
(next) => {
|
|
4641
|
+
onChange?.(next);
|
|
4642
|
+
},
|
|
4643
|
+
[onChange]
|
|
4644
|
+
);
|
|
4645
|
+
const [selectedValues, setSelectedValues] = useControllableState({
|
|
4646
|
+
value,
|
|
4647
|
+
defaultValue: defaultValue ?? [],
|
|
4648
|
+
onChange: handleChange
|
|
4649
|
+
});
|
|
4650
|
+
const { nodes: optionNodes } = React38.useMemo(() => walkNativeOptions(children), [children]);
|
|
4651
|
+
const handleNativeChange = React38.useCallback(
|
|
4652
|
+
(e) => {
|
|
4653
|
+
const next = Array.from(e.target.selectedOptions, (o) => o.value);
|
|
4654
|
+
setSelectedValues(next);
|
|
4655
|
+
},
|
|
4656
|
+
[setSelectedValues]
|
|
4657
|
+
);
|
|
4658
|
+
return /* @__PURE__ */ jsx26(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsx26(
|
|
4659
|
+
"select",
|
|
4660
|
+
{
|
|
4661
|
+
className: Select_default.nativeSelect,
|
|
4662
|
+
"data-multiple": "true",
|
|
4663
|
+
disabled,
|
|
4664
|
+
multiple: true,
|
|
4665
|
+
value: selectedValues,
|
|
4666
|
+
onChange: handleNativeChange,
|
|
4667
|
+
...toDataAttributes({ size, "has-error": hasError }),
|
|
4668
|
+
children: optionNodes
|
|
4669
|
+
}
|
|
4670
|
+
) });
|
|
4671
|
+
}
|
|
4672
|
+
SelectNativeMultiRoot.displayName = "SelectNativeMultiRoot";
|
|
4419
4673
|
var Select = {
|
|
4420
4674
|
Root: SelectRoot,
|
|
4421
4675
|
Trigger: SelectTrigger,
|
|
@@ -7068,21 +7322,6 @@ function handleMenuNavigationKeyDown(e, container) {
|
|
|
7068
7322
|
// src/components/dropdown/useDropdownPosition.ts
|
|
7069
7323
|
import * as React48 from "react";
|
|
7070
7324
|
|
|
7071
|
-
// src/internal/scrollAncestors.ts
|
|
7072
|
-
var SCROLLABLE = /^(auto|scroll|overlay)$/;
|
|
7073
|
-
function getScrollContainers(node) {
|
|
7074
|
-
const out = [window];
|
|
7075
|
-
if (!node || typeof window === "undefined") return out;
|
|
7076
|
-
for (let el = node.parentElement; el; el = el.parentElement) {
|
|
7077
|
-
const { overflowX, overflowY } = window.getComputedStyle(el);
|
|
7078
|
-
if (SCROLLABLE.test(overflowY) || SCROLLABLE.test(overflowX)) {
|
|
7079
|
-
out.push(el);
|
|
7080
|
-
}
|
|
7081
|
-
}
|
|
7082
|
-
if (window.visualViewport) out.push(window.visualViewport);
|
|
7083
|
-
return out;
|
|
7084
|
-
}
|
|
7085
|
-
|
|
7086
7325
|
// src/components/dropdown/dropdownGeometry.ts
|
|
7087
7326
|
var DROPDOWN_MIN_MAX_HEIGHT = 120;
|
|
7088
7327
|
function getDropdownMaxHeightForAnchorSide(anchor, side, viewportHeight, panelOffsetPx, viewportPadPx) {
|
|
@@ -10146,9 +10385,470 @@ function TagIcon({ children, className }) {
|
|
|
10146
10385
|
TagIcon.displayName = "TagIcon";
|
|
10147
10386
|
var Tag = { Root: TagRoot, Icon: TagIcon };
|
|
10148
10387
|
|
|
10149
|
-
// src/components/
|
|
10388
|
+
// src/components/tag-select/TagSelect.tsx
|
|
10150
10389
|
import * as React71 from "react";
|
|
10151
10390
|
|
|
10391
|
+
// src/components/tag-select/TagSelect.module.css
|
|
10392
|
+
var TagSelect_default = {
|
|
10393
|
+
control: "TagSelect_control",
|
|
10394
|
+
chips: "TagSelect_chips",
|
|
10395
|
+
chip: "TagSelect_chip",
|
|
10396
|
+
chipBadge: "TagSelect_chipBadge",
|
|
10397
|
+
chipLabel: "TagSelect_chipLabel",
|
|
10398
|
+
chipRemove: "TagSelect_chipRemove",
|
|
10399
|
+
removeIcon: "TagSelect_removeIcon",
|
|
10400
|
+
input: "TagSelect_input",
|
|
10401
|
+
inputCollapsed: "TagSelect_inputCollapsed",
|
|
10402
|
+
chevronSlot: "TagSelect_chevronSlot",
|
|
10403
|
+
chevron: "TagSelect_chevron",
|
|
10404
|
+
panelInner: "TagSelect_panelInner",
|
|
10405
|
+
hint: "TagSelect_hint",
|
|
10406
|
+
optionRow: "TagSelect_optionRow",
|
|
10407
|
+
createRow: "TagSelect_createRow",
|
|
10408
|
+
createLabel: "TagSelect_createLabel"
|
|
10409
|
+
};
|
|
10410
|
+
|
|
10411
|
+
// src/components/tag-select/TagSelect.tsx
|
|
10412
|
+
import { jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
10413
|
+
var CREATE_VALUE = "__prime_tag_select_create__";
|
|
10414
|
+
function normalizeList(selected, options, defaultTagColor) {
|
|
10415
|
+
return selected.map((v) => {
|
|
10416
|
+
const o = options.find((x) => x.value === v);
|
|
10417
|
+
return {
|
|
10418
|
+
value: v,
|
|
10419
|
+
label: o?.label ?? v,
|
|
10420
|
+
color: o?.color ?? defaultTagColor
|
|
10421
|
+
};
|
|
10422
|
+
});
|
|
10423
|
+
}
|
|
10424
|
+
function filterOptions(options, query) {
|
|
10425
|
+
const q = query.trim().toLowerCase();
|
|
10426
|
+
if (q.length === 0) return options;
|
|
10427
|
+
return options.filter((o) => {
|
|
10428
|
+
if (o.disabled) return false;
|
|
10429
|
+
return o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q);
|
|
10430
|
+
});
|
|
10431
|
+
}
|
|
10432
|
+
function optionsForList(options, query, selected) {
|
|
10433
|
+
return filterOptions(options, query).filter((o) => !selected.includes(o.value));
|
|
10434
|
+
}
|
|
10435
|
+
function shouldShowCreate(creatable, inputTrim, selected, options) {
|
|
10436
|
+
if (!creatable || inputTrim.length === 0) return false;
|
|
10437
|
+
if (selected.includes(inputTrim)) return false;
|
|
10438
|
+
const lower = inputTrim.toLowerCase();
|
|
10439
|
+
const exists = options.some(
|
|
10440
|
+
(o) => o.value === inputTrim || o.label.toLowerCase() === lower || o.value.toLowerCase() === lower
|
|
10441
|
+
);
|
|
10442
|
+
return !exists;
|
|
10443
|
+
}
|
|
10444
|
+
function TagSelectRoot({
|
|
10445
|
+
options,
|
|
10446
|
+
value: valueProp,
|
|
10447
|
+
defaultValue = [],
|
|
10448
|
+
onValueChange,
|
|
10449
|
+
creatable = false,
|
|
10450
|
+
onCreated,
|
|
10451
|
+
defaultTagColor = "gray",
|
|
10452
|
+
hint = "Select an option or create one",
|
|
10453
|
+
createActionLabel = "Create",
|
|
10454
|
+
disabled = false,
|
|
10455
|
+
placeholder = "",
|
|
10456
|
+
hasError = false,
|
|
10457
|
+
size = "m",
|
|
10458
|
+
id: idProp,
|
|
10459
|
+
className,
|
|
10460
|
+
"aria-label": ariaLabel,
|
|
10461
|
+
"aria-labelledby": ariaLabelledBy
|
|
10462
|
+
}) {
|
|
10463
|
+
const generatedId = React71.useId();
|
|
10464
|
+
const rootId = idProp ?? generatedId;
|
|
10465
|
+
const listboxId = `${rootId}-listbox`;
|
|
10466
|
+
const inputId = `${rootId}-input`;
|
|
10467
|
+
const [selected, setSelected] = useControllableState({
|
|
10468
|
+
value: valueProp,
|
|
10469
|
+
defaultValue,
|
|
10470
|
+
onChange: onValueChange
|
|
10471
|
+
});
|
|
10472
|
+
const [inputValue, setInputValue] = React71.useState("");
|
|
10473
|
+
const [inputFocused, setInputFocused] = React71.useState(false);
|
|
10474
|
+
const [open, setOpen] = React71.useState(false);
|
|
10475
|
+
const [highlightedValue, setHighlightedValue] = React71.useState(void 0);
|
|
10476
|
+
const triggerRef = React71.useRef(null);
|
|
10477
|
+
const inputRef = React71.useRef(null);
|
|
10478
|
+
const listboxRef = React71.useRef(null);
|
|
10479
|
+
const overlayPortalLayer = useOverlayPortalLayer();
|
|
10480
|
+
const { resolvedSide, update } = usePosition(triggerRef, listboxRef, {
|
|
10481
|
+
side: "bottom",
|
|
10482
|
+
align: "start"
|
|
10483
|
+
});
|
|
10484
|
+
const updateRef = React71.useRef(update);
|
|
10485
|
+
updateRef.current = update;
|
|
10486
|
+
const inputTrim = inputValue.trim();
|
|
10487
|
+
const filtered = React71.useMemo(
|
|
10488
|
+
() => optionsForList(options, inputValue, selected),
|
|
10489
|
+
[options, inputValue, selected]
|
|
10490
|
+
);
|
|
10491
|
+
const showCreate = shouldShowCreate(creatable, inputTrim, selected, options);
|
|
10492
|
+
const hasPanelContent = filtered.length > 0 || showCreate;
|
|
10493
|
+
const flatOptionValues = React71.useMemo(() => {
|
|
10494
|
+
const v = [];
|
|
10495
|
+
if (showCreate) v.push(CREATE_VALUE);
|
|
10496
|
+
for (const o of filtered) {
|
|
10497
|
+
if (!o.disabled) v.push(o.value);
|
|
10498
|
+
}
|
|
10499
|
+
return v;
|
|
10500
|
+
}, [filtered, showCreate]);
|
|
10501
|
+
React71.useLayoutEffect(() => {
|
|
10502
|
+
if (!open) return;
|
|
10503
|
+
updateRef.current();
|
|
10504
|
+
const raf = requestAnimationFrame(() => updateRef.current());
|
|
10505
|
+
return () => cancelAnimationFrame(raf);
|
|
10506
|
+
}, [open]);
|
|
10507
|
+
React71.useEffect(() => {
|
|
10508
|
+
if (!open) return;
|
|
10509
|
+
let rafCoalesce = 0;
|
|
10510
|
+
const schedule = () => {
|
|
10511
|
+
cancelAnimationFrame(rafCoalesce);
|
|
10512
|
+
rafCoalesce = requestAnimationFrame(() => updateRef.current());
|
|
10513
|
+
};
|
|
10514
|
+
window.addEventListener("resize", schedule);
|
|
10515
|
+
const scrollTargets = getScrollContainers(triggerRef.current);
|
|
10516
|
+
for (const t of scrollTargets) {
|
|
10517
|
+
t.addEventListener("scroll", schedule, { passive: true });
|
|
10518
|
+
}
|
|
10519
|
+
const vv = window.visualViewport;
|
|
10520
|
+
vv?.addEventListener("resize", schedule);
|
|
10521
|
+
const panel = listboxRef.current;
|
|
10522
|
+
let ro = null;
|
|
10523
|
+
if (typeof ResizeObserver !== "undefined" && panel) {
|
|
10524
|
+
ro = new ResizeObserver(schedule);
|
|
10525
|
+
ro.observe(panel);
|
|
10526
|
+
}
|
|
10527
|
+
return () => {
|
|
10528
|
+
cancelAnimationFrame(rafCoalesce);
|
|
10529
|
+
window.removeEventListener("resize", schedule);
|
|
10530
|
+
for (const t of scrollTargets) {
|
|
10531
|
+
t.removeEventListener("scroll", schedule);
|
|
10532
|
+
}
|
|
10533
|
+
vv?.removeEventListener("resize", schedule);
|
|
10534
|
+
ro?.disconnect();
|
|
10535
|
+
};
|
|
10536
|
+
}, [open]);
|
|
10537
|
+
React71.useEffect(() => {
|
|
10538
|
+
if (!open) {
|
|
10539
|
+
setHighlightedValue(void 0);
|
|
10540
|
+
return;
|
|
10541
|
+
}
|
|
10542
|
+
if (flatOptionValues.length === 0) {
|
|
10543
|
+
setHighlightedValue(void 0);
|
|
10544
|
+
return;
|
|
10545
|
+
}
|
|
10546
|
+
setHighlightedValue(
|
|
10547
|
+
(prev) => prev && flatOptionValues.includes(prev) ? prev : flatOptionValues[0]
|
|
10548
|
+
);
|
|
10549
|
+
}, [open, flatOptionValues]);
|
|
10550
|
+
React71.useEffect(() => {
|
|
10551
|
+
if (!open) return;
|
|
10552
|
+
if (!hasPanelContent) setOpen(false);
|
|
10553
|
+
}, [open, hasPanelContent]);
|
|
10554
|
+
useEscapeKey({ enabled: open, onEscape: () => setOpen(false) });
|
|
10555
|
+
useOutsideClick({
|
|
10556
|
+
refs: [triggerRef, listboxRef],
|
|
10557
|
+
enabled: open,
|
|
10558
|
+
onOutsideClick: () => setOpen(false)
|
|
10559
|
+
});
|
|
10560
|
+
const toggleValue = React71.useCallback(
|
|
10561
|
+
(value) => {
|
|
10562
|
+
setSelected((prev) => {
|
|
10563
|
+
if (prev.includes(value)) {
|
|
10564
|
+
return prev.filter((x) => x !== value);
|
|
10565
|
+
}
|
|
10566
|
+
return [...prev, value];
|
|
10567
|
+
});
|
|
10568
|
+
},
|
|
10569
|
+
[setSelected]
|
|
10570
|
+
);
|
|
10571
|
+
const handleSelectFromList = React71.useCallback(
|
|
10572
|
+
(rawValue) => {
|
|
10573
|
+
if (rawValue === CREATE_VALUE) {
|
|
10574
|
+
const v = inputTrim;
|
|
10575
|
+
if (v.length === 0) return;
|
|
10576
|
+
setSelected((prev) => {
|
|
10577
|
+
if (prev.includes(v)) return prev;
|
|
10578
|
+
onCreated?.(v);
|
|
10579
|
+
return [...prev, v];
|
|
10580
|
+
});
|
|
10581
|
+
setInputValue("");
|
|
10582
|
+
return;
|
|
10583
|
+
}
|
|
10584
|
+
toggleValue(rawValue);
|
|
10585
|
+
setInputValue("");
|
|
10586
|
+
},
|
|
10587
|
+
[inputTrim, onCreated, setSelected, toggleValue]
|
|
10588
|
+
);
|
|
10589
|
+
const getItems = React71.useCallback(() => queryEnabledSelectOptions(listboxRef.current), []);
|
|
10590
|
+
const onListboxKeyDown = (e) => {
|
|
10591
|
+
handleSelectListboxKeyDown(e, {
|
|
10592
|
+
items: getItems(),
|
|
10593
|
+
highlightedValue,
|
|
10594
|
+
setHighlightedValue,
|
|
10595
|
+
onSelect: (v) => {
|
|
10596
|
+
handleSelectFromList(v);
|
|
10597
|
+
},
|
|
10598
|
+
onClose: () => setOpen(false)
|
|
10599
|
+
});
|
|
10600
|
+
};
|
|
10601
|
+
const onInputKeyDown = (e) => {
|
|
10602
|
+
if (disabled) return;
|
|
10603
|
+
if (e.key === "Backspace" && inputValue.length === 0 && selected.length > 0) {
|
|
10604
|
+
e.preventDefault();
|
|
10605
|
+
setSelected((prev) => prev.slice(0, -1));
|
|
10606
|
+
return;
|
|
10607
|
+
}
|
|
10608
|
+
if (e.key === "Escape") {
|
|
10609
|
+
if (open) {
|
|
10610
|
+
e.preventDefault();
|
|
10611
|
+
setOpen(false);
|
|
10612
|
+
}
|
|
10613
|
+
return;
|
|
10614
|
+
}
|
|
10615
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " ") {
|
|
10616
|
+
if (!open) {
|
|
10617
|
+
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
10618
|
+
e.preventDefault();
|
|
10619
|
+
if (filtered.length > 0 || showCreate) setOpen(true);
|
|
10620
|
+
}
|
|
10621
|
+
return;
|
|
10622
|
+
}
|
|
10623
|
+
if (flatOptionValues.length === 0) return;
|
|
10624
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
10625
|
+
e.preventDefault();
|
|
10626
|
+
const hv = highlightedValue ?? flatOptionValues[0];
|
|
10627
|
+
if (hv === CREATE_VALUE) {
|
|
10628
|
+
handleSelectFromList(CREATE_VALUE);
|
|
10629
|
+
} else if (hv) {
|
|
10630
|
+
const o = options.find((x) => x.value === hv);
|
|
10631
|
+
if (o && !o.disabled) {
|
|
10632
|
+
handleSelectFromList(o.value);
|
|
10633
|
+
}
|
|
10634
|
+
}
|
|
10635
|
+
return;
|
|
10636
|
+
}
|
|
10637
|
+
handleSelectListboxKeyDown(e, {
|
|
10638
|
+
items: getItems(),
|
|
10639
|
+
highlightedValue,
|
|
10640
|
+
setHighlightedValue,
|
|
10641
|
+
onSelect: (v) => handleSelectFromList(v),
|
|
10642
|
+
onClose: () => setOpen(false)
|
|
10643
|
+
});
|
|
10644
|
+
}
|
|
10645
|
+
};
|
|
10646
|
+
const chips = normalizeList(selected, options, defaultTagColor);
|
|
10647
|
+
const isEmpty = selected.length === 0 && inputTrim.length === 0;
|
|
10648
|
+
const inputCollapsed = !inputFocused && inputTrim.length === 0 && selected.length > 0;
|
|
10649
|
+
const focusInput = () => {
|
|
10650
|
+
inputRef.current?.focus();
|
|
10651
|
+
};
|
|
10652
|
+
const handleInputBlur = React71.useCallback((e) => {
|
|
10653
|
+
const next = e.relatedTarget;
|
|
10654
|
+
if (next instanceof Node && triggerRef.current?.contains(next)) {
|
|
10655
|
+
return;
|
|
10656
|
+
}
|
|
10657
|
+
window.requestAnimationFrame(() => {
|
|
10658
|
+
if (triggerRef.current?.contains(document.activeElement)) {
|
|
10659
|
+
return;
|
|
10660
|
+
}
|
|
10661
|
+
setInputFocused(false);
|
|
10662
|
+
setInputValue("");
|
|
10663
|
+
});
|
|
10664
|
+
}, []);
|
|
10665
|
+
return /* @__PURE__ */ jsxs31(ControlSizeProvider, { value: size, children: [
|
|
10666
|
+
/* @__PURE__ */ jsxs31(
|
|
10667
|
+
"div",
|
|
10668
|
+
{
|
|
10669
|
+
ref: triggerRef,
|
|
10670
|
+
className: cx(TagSelect_default.control, className),
|
|
10671
|
+
onClick: () => {
|
|
10672
|
+
if (!disabled) {
|
|
10673
|
+
focusInput();
|
|
10674
|
+
if (hasPanelContent) setOpen(true);
|
|
10675
|
+
}
|
|
10676
|
+
},
|
|
10677
|
+
...toDataAttributes({
|
|
10678
|
+
size,
|
|
10679
|
+
open,
|
|
10680
|
+
empty: isEmpty ? true : void 0,
|
|
10681
|
+
disabled: disabled ? true : void 0,
|
|
10682
|
+
"has-error": hasError ? true : void 0
|
|
10683
|
+
}),
|
|
10684
|
+
children: [
|
|
10685
|
+
/* @__PURE__ */ jsxs31("div", { className: TagSelect_default.chips, children: [
|
|
10686
|
+
chips.map((c) => /* @__PURE__ */ jsx57("span", { className: TagSelect_default.chip, children: /* @__PURE__ */ jsxs31(Badge.Root, { color: c.color, variant: "filled", className: TagSelect_default.chipBadge, children: [
|
|
10687
|
+
/* @__PURE__ */ jsx57("span", { className: TagSelect_default.chipLabel, children: c.label }),
|
|
10688
|
+
/* @__PURE__ */ jsx57(
|
|
10689
|
+
"button",
|
|
10690
|
+
{
|
|
10691
|
+
type: "button",
|
|
10692
|
+
className: TagSelect_default.chipRemove,
|
|
10693
|
+
"aria-label": `Remove ${c.label}`,
|
|
10694
|
+
disabled,
|
|
10695
|
+
onMouseDown: (e) => {
|
|
10696
|
+
e.preventDefault();
|
|
10697
|
+
},
|
|
10698
|
+
onClick: (e) => {
|
|
10699
|
+
e.stopPropagation();
|
|
10700
|
+
setSelected((prev) => prev.filter((x) => x !== c.value));
|
|
10701
|
+
},
|
|
10702
|
+
children: /* @__PURE__ */ jsx57(
|
|
10703
|
+
"svg",
|
|
10704
|
+
{
|
|
10705
|
+
className: TagSelect_default.removeIcon,
|
|
10706
|
+
viewBox: "0 0 12 12",
|
|
10707
|
+
fill: "none",
|
|
10708
|
+
"aria-hidden": "true",
|
|
10709
|
+
children: /* @__PURE__ */ jsx57(
|
|
10710
|
+
"path",
|
|
10711
|
+
{
|
|
10712
|
+
d: "M2 2l8 8M10 2l-8 8",
|
|
10713
|
+
stroke: "currentColor",
|
|
10714
|
+
strokeWidth: "1.5",
|
|
10715
|
+
strokeLinecap: "round"
|
|
10716
|
+
}
|
|
10717
|
+
)
|
|
10718
|
+
}
|
|
10719
|
+
)
|
|
10720
|
+
}
|
|
10721
|
+
)
|
|
10722
|
+
] }) }, c.value)),
|
|
10723
|
+
/* @__PURE__ */ jsx57(
|
|
10724
|
+
"input",
|
|
10725
|
+
{
|
|
10726
|
+
ref: inputRef,
|
|
10727
|
+
id: inputId,
|
|
10728
|
+
type: "text",
|
|
10729
|
+
role: "combobox",
|
|
10730
|
+
"aria-expanded": open,
|
|
10731
|
+
"aria-controls": listboxId,
|
|
10732
|
+
"aria-autocomplete": "list",
|
|
10733
|
+
"aria-label": ariaLabel,
|
|
10734
|
+
"aria-labelledby": ariaLabelledBy,
|
|
10735
|
+
disabled,
|
|
10736
|
+
placeholder: selected.length === 0 ? placeholder : void 0,
|
|
10737
|
+
className: cx(TagSelect_default.input, inputCollapsed && TagSelect_default.inputCollapsed),
|
|
10738
|
+
value: inputValue,
|
|
10739
|
+
onChange: (e) => {
|
|
10740
|
+
const next = e.target.value;
|
|
10741
|
+
setInputValue(next);
|
|
10742
|
+
const nextTrim = next.trim();
|
|
10743
|
+
const nextFiltered = optionsForList(options, next, selected);
|
|
10744
|
+
const nextShowCreate = shouldShowCreate(creatable, nextTrim, selected, options);
|
|
10745
|
+
if (nextFiltered.length > 0 || nextShowCreate) {
|
|
10746
|
+
setOpen(true);
|
|
10747
|
+
} else {
|
|
10748
|
+
setOpen(false);
|
|
10749
|
+
}
|
|
10750
|
+
},
|
|
10751
|
+
onKeyDown: onInputKeyDown,
|
|
10752
|
+
onFocus: () => {
|
|
10753
|
+
setInputFocused(true);
|
|
10754
|
+
if (!disabled && hasPanelContent) setOpen(true);
|
|
10755
|
+
},
|
|
10756
|
+
onBlur: handleInputBlur
|
|
10757
|
+
}
|
|
10758
|
+
)
|
|
10759
|
+
] }),
|
|
10760
|
+
/* @__PURE__ */ jsx57("span", { className: TagSelect_default.chevronSlot, "aria-hidden": true, children: /* @__PURE__ */ jsx57("span", { className: TagSelect_default.chevron }) })
|
|
10761
|
+
]
|
|
10762
|
+
}
|
|
10763
|
+
),
|
|
10764
|
+
/* @__PURE__ */ jsx57(Portal, { children: /* @__PURE__ */ jsxs31(
|
|
10765
|
+
ScrollContainer,
|
|
10766
|
+
{
|
|
10767
|
+
ref: listboxRef,
|
|
10768
|
+
id: listboxId,
|
|
10769
|
+
role: "listbox",
|
|
10770
|
+
"aria-multiselectable": "true",
|
|
10771
|
+
"aria-hidden": !open,
|
|
10772
|
+
tabIndex: -1,
|
|
10773
|
+
"data-react-aria-top-layer": "true",
|
|
10774
|
+
"data-overlay-portal-layer": overlayPortalLayer,
|
|
10775
|
+
className: cx(Select_default.content, TagSelect_default.panelInner),
|
|
10776
|
+
onKeyDown: onListboxKeyDown,
|
|
10777
|
+
style: { display: open ? void 0 : "none" },
|
|
10778
|
+
...toDataAttributes({ side: resolvedSide, size }),
|
|
10779
|
+
children: [
|
|
10780
|
+
hint ? /* @__PURE__ */ jsx57("div", { className: TagSelect_default.hint, children: /* @__PURE__ */ jsx57(Typography.Root, { as: "div", variant: "body-small", tone: "muted", children: hint }) }) : null,
|
|
10781
|
+
showCreate ? /* @__PURE__ */ jsxs31(
|
|
10782
|
+
"button",
|
|
10783
|
+
{
|
|
10784
|
+
type: "button",
|
|
10785
|
+
role: "option",
|
|
10786
|
+
"aria-selected": false,
|
|
10787
|
+
className: TagSelect_default.createRow,
|
|
10788
|
+
...toDataAttributes({
|
|
10789
|
+
value: CREATE_VALUE,
|
|
10790
|
+
label: inputTrim,
|
|
10791
|
+
highlighted: highlightedValue === CREATE_VALUE,
|
|
10792
|
+
disabled: false
|
|
10793
|
+
}),
|
|
10794
|
+
onMouseDown: (e) => {
|
|
10795
|
+
e.preventDefault();
|
|
10796
|
+
},
|
|
10797
|
+
onMouseEnter: () => setHighlightedValue(CREATE_VALUE),
|
|
10798
|
+
onClick: () => handleSelectFromList(CREATE_VALUE),
|
|
10799
|
+
children: [
|
|
10800
|
+
/* @__PURE__ */ jsx57(
|
|
10801
|
+
Typography.Root,
|
|
10802
|
+
{
|
|
10803
|
+
as: "span",
|
|
10804
|
+
variant: "body-small",
|
|
10805
|
+
tone: "muted",
|
|
10806
|
+
className: TagSelect_default.createLabel,
|
|
10807
|
+
children: createActionLabel
|
|
10808
|
+
}
|
|
10809
|
+
),
|
|
10810
|
+
/* @__PURE__ */ jsx57(Badge.Root, { color: defaultTagColor, variant: "filled", children: inputTrim })
|
|
10811
|
+
]
|
|
10812
|
+
},
|
|
10813
|
+
CREATE_VALUE
|
|
10814
|
+
) : null,
|
|
10815
|
+
filtered.map((o) => /* @__PURE__ */ jsx57(
|
|
10816
|
+
"button",
|
|
10817
|
+
{
|
|
10818
|
+
type: "button",
|
|
10819
|
+
role: "option",
|
|
10820
|
+
"aria-selected": false,
|
|
10821
|
+
disabled: o.disabled,
|
|
10822
|
+
className: TagSelect_default.optionRow,
|
|
10823
|
+
...toDataAttributes({
|
|
10824
|
+
value: o.value,
|
|
10825
|
+
label: o.label,
|
|
10826
|
+
highlighted: highlightedValue === o.value,
|
|
10827
|
+
selected: false,
|
|
10828
|
+
disabled: Boolean(o.disabled)
|
|
10829
|
+
}),
|
|
10830
|
+
onMouseDown: (e) => {
|
|
10831
|
+
if (!o.disabled) e.preventDefault();
|
|
10832
|
+
},
|
|
10833
|
+
onMouseEnter: () => !o.disabled && setHighlightedValue(o.value),
|
|
10834
|
+
onClick: () => !o.disabled && handleSelectFromList(o.value),
|
|
10835
|
+
children: /* @__PURE__ */ jsx57(Badge.Root, { color: o.color ?? defaultTagColor, variant: "filled", children: o.label })
|
|
10836
|
+
},
|
|
10837
|
+
o.value
|
|
10838
|
+
))
|
|
10839
|
+
]
|
|
10840
|
+
}
|
|
10841
|
+
) })
|
|
10842
|
+
] });
|
|
10843
|
+
}
|
|
10844
|
+
TagSelectRoot.displayName = "TagSelectRoot";
|
|
10845
|
+
var TagSelect = {
|
|
10846
|
+
Root: TagSelectRoot
|
|
10847
|
+
};
|
|
10848
|
+
|
|
10849
|
+
// src/components/textarea/Textarea.tsx
|
|
10850
|
+
import * as React72 from "react";
|
|
10851
|
+
|
|
10152
10852
|
// src/components/textarea/Textarea.module.css
|
|
10153
10853
|
var Textarea_default = {
|
|
10154
10854
|
field: "Textarea_field",
|
|
@@ -10164,11 +10864,11 @@ var Textarea_default = {
|
|
|
10164
10864
|
};
|
|
10165
10865
|
|
|
10166
10866
|
// src/components/textarea/Textarea.tsx
|
|
10167
|
-
import { jsx as
|
|
10867
|
+
import { jsx as jsx58, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
10168
10868
|
var [TextareaProvider, useTextareaContext] = createComponentContext("Textarea");
|
|
10169
10869
|
function TextareaCharCounter({ current, max }) {
|
|
10170
10870
|
const overflow = current > max;
|
|
10171
|
-
return /* @__PURE__ */
|
|
10871
|
+
return /* @__PURE__ */ jsxs32(
|
|
10172
10872
|
"span",
|
|
10173
10873
|
{
|
|
10174
10874
|
className: Textarea_default.charCounter,
|
|
@@ -10186,8 +10886,8 @@ TextareaCharCounter.displayName = "Textarea.CharCounter";
|
|
|
10186
10886
|
function partitionTextareaChildren(children) {
|
|
10187
10887
|
const counters = [];
|
|
10188
10888
|
const rest = [];
|
|
10189
|
-
|
|
10190
|
-
if (
|
|
10889
|
+
React72.Children.forEach(children, (child) => {
|
|
10890
|
+
if (React72.isValidElement(child) && child.type === TextareaCharCounter) {
|
|
10191
10891
|
counters.push(child);
|
|
10192
10892
|
} else if (child != null && child !== false) {
|
|
10193
10893
|
rest.push(child);
|
|
@@ -10195,7 +10895,7 @@ function partitionTextareaChildren(children) {
|
|
|
10195
10895
|
});
|
|
10196
10896
|
return { counters, rest };
|
|
10197
10897
|
}
|
|
10198
|
-
var TextareaRoot =
|
|
10898
|
+
var TextareaRoot = React72.forwardRef(
|
|
10199
10899
|
({
|
|
10200
10900
|
id,
|
|
10201
10901
|
className,
|
|
@@ -10212,12 +10912,12 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10212
10912
|
children,
|
|
10213
10913
|
...rest
|
|
10214
10914
|
}, ref) => {
|
|
10215
|
-
const rawId =
|
|
10915
|
+
const rawId = React72.useId();
|
|
10216
10916
|
const inputId = id ?? rawId;
|
|
10217
10917
|
const hintId = `${inputId}-hint`;
|
|
10218
10918
|
const errorId = `${inputId}-error`;
|
|
10219
|
-
const [hasHint, setHasHint] =
|
|
10220
|
-
const [hasError, setHasError] =
|
|
10919
|
+
const [hasHint, setHasHint] = React72.useState(false);
|
|
10920
|
+
const [hasError, setHasError] = React72.useState(false);
|
|
10221
10921
|
const invalid = variant === "error" || hasError;
|
|
10222
10922
|
const resolvedAriaInvalid = ariaInvalid ?? (invalid || void 0);
|
|
10223
10923
|
const parts = [
|
|
@@ -10226,25 +10926,25 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10226
10926
|
hasError ? errorId : void 0
|
|
10227
10927
|
].filter(Boolean);
|
|
10228
10928
|
const describedBy = parts.length > 0 ? parts.join(" ") : void 0;
|
|
10229
|
-
const registerHint =
|
|
10230
|
-
const unregisterHint =
|
|
10231
|
-
const registerError =
|
|
10232
|
-
const unregisterError =
|
|
10233
|
-
const wrapperRef =
|
|
10929
|
+
const registerHint = React72.useCallback(() => setHasHint(true), []);
|
|
10930
|
+
const unregisterHint = React72.useCallback(() => setHasHint(false), []);
|
|
10931
|
+
const registerError = React72.useCallback(() => setHasError(true), []);
|
|
10932
|
+
const unregisterError = React72.useCallback(() => setHasError(false), []);
|
|
10933
|
+
const wrapperRef = React72.useRef(null);
|
|
10234
10934
|
const { counters: counterChildren, rest: otherChildren } = partitionTextareaChildren(children);
|
|
10235
10935
|
const showFooter = counterChildren.length > 0;
|
|
10236
|
-
|
|
10936
|
+
React72.useLayoutEffect(() => {
|
|
10237
10937
|
if (!autoResize || !wrapperRef.current) return;
|
|
10238
10938
|
const textarea = wrapperRef.current.querySelector("textarea");
|
|
10239
10939
|
if (textarea) {
|
|
10240
10940
|
wrapperRef.current.dataset.value = textarea.value;
|
|
10241
10941
|
}
|
|
10242
10942
|
}, [autoResize]);
|
|
10243
|
-
|
|
10943
|
+
React72.useEffect(() => {
|
|
10244
10944
|
if (!autoResize || !wrapperRef.current || typeof value !== "string") return;
|
|
10245
10945
|
wrapperRef.current.dataset.value = value;
|
|
10246
10946
|
}, [autoResize, value]);
|
|
10247
|
-
const handleInput =
|
|
10947
|
+
const handleInput = React72.useCallback(
|
|
10248
10948
|
(e) => {
|
|
10249
10949
|
if (autoResize && wrapperRef.current) {
|
|
10250
10950
|
wrapperRef.current.dataset.value = e.currentTarget.value;
|
|
@@ -10253,7 +10953,7 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10253
10953
|
},
|
|
10254
10954
|
[autoResize, onInput]
|
|
10255
10955
|
);
|
|
10256
|
-
const ctxValue =
|
|
10956
|
+
const ctxValue = React72.useMemo(
|
|
10257
10957
|
() => ({
|
|
10258
10958
|
hintId,
|
|
10259
10959
|
errorId,
|
|
@@ -10277,7 +10977,7 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10277
10977
|
unregisterError
|
|
10278
10978
|
]
|
|
10279
10979
|
);
|
|
10280
|
-
const textareaEl = /* @__PURE__ */
|
|
10980
|
+
const textareaEl = /* @__PURE__ */ jsx58(
|
|
10281
10981
|
"textarea",
|
|
10282
10982
|
{
|
|
10283
10983
|
ref,
|
|
@@ -10293,9 +10993,9 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10293
10993
|
...rest
|
|
10294
10994
|
}
|
|
10295
10995
|
);
|
|
10296
|
-
const textareaBlock = autoResize ? /* @__PURE__ */
|
|
10297
|
-
return /* @__PURE__ */
|
|
10298
|
-
/* @__PURE__ */
|
|
10996
|
+
const textareaBlock = autoResize ? /* @__PURE__ */ jsx58("div", { ref: wrapperRef, className: Textarea_default.autoResize, children: textareaEl }) : textareaEl;
|
|
10997
|
+
return /* @__PURE__ */ jsx58(TextareaProvider, { value: ctxValue, children: /* @__PURE__ */ jsx58(ControlSizeProvider, { value: size, children: /* @__PURE__ */ jsxs32("div", { className: Textarea_default.field, ...toDataAttributes({ size }), children: [
|
|
10998
|
+
/* @__PURE__ */ jsx58(
|
|
10299
10999
|
"label",
|
|
10300
11000
|
{
|
|
10301
11001
|
htmlFor: inputId,
|
|
@@ -10306,9 +11006,9 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10306
11006
|
readonly: Boolean(readOnly),
|
|
10307
11007
|
size
|
|
10308
11008
|
}),
|
|
10309
|
-
children: /* @__PURE__ */
|
|
10310
|
-
/* @__PURE__ */
|
|
10311
|
-
showFooter ? /* @__PURE__ */
|
|
11009
|
+
children: /* @__PURE__ */ jsxs32("div", { className: Textarea_default.controlStack, children: [
|
|
11010
|
+
/* @__PURE__ */ jsx58("div", { className: Textarea_default.textareaRegion, children: textareaBlock }),
|
|
11011
|
+
showFooter ? /* @__PURE__ */ jsx58("div", { className: Textarea_default.controlFooter, children: counterChildren }) : null
|
|
10312
11012
|
] })
|
|
10313
11013
|
}
|
|
10314
11014
|
),
|
|
@@ -10319,13 +11019,13 @@ var TextareaRoot = React71.forwardRef(
|
|
|
10319
11019
|
TextareaRoot.displayName = "Textarea.Root";
|
|
10320
11020
|
function TextareaHint({ children, className, ...rest }) {
|
|
10321
11021
|
const { hintId, registerHint, unregisterHint, size, disabled, readOnly } = useTextareaContext();
|
|
10322
|
-
|
|
11022
|
+
React72.useLayoutEffect(() => {
|
|
10323
11023
|
registerHint();
|
|
10324
11024
|
return () => {
|
|
10325
11025
|
unregisterHint();
|
|
10326
11026
|
};
|
|
10327
11027
|
}, [registerHint, unregisterHint]);
|
|
10328
|
-
return /* @__PURE__ */
|
|
11028
|
+
return /* @__PURE__ */ jsx58(
|
|
10329
11029
|
Hint.Root,
|
|
10330
11030
|
{
|
|
10331
11031
|
id: hintId,
|
|
@@ -10340,13 +11040,13 @@ function TextareaHint({ children, className, ...rest }) {
|
|
|
10340
11040
|
TextareaHint.displayName = "Textarea.Hint";
|
|
10341
11041
|
function TextareaError({ children, className, ...rest }) {
|
|
10342
11042
|
const { errorId, registerError, unregisterError, size } = useTextareaContext();
|
|
10343
|
-
|
|
11043
|
+
React72.useLayoutEffect(() => {
|
|
10344
11044
|
registerError();
|
|
10345
11045
|
return () => {
|
|
10346
11046
|
unregisterError();
|
|
10347
11047
|
};
|
|
10348
11048
|
}, [registerError, unregisterError]);
|
|
10349
|
-
return /* @__PURE__ */
|
|
11049
|
+
return /* @__PURE__ */ jsx58(
|
|
10350
11050
|
Hint.Root,
|
|
10351
11051
|
{
|
|
10352
11052
|
id: errorId,
|
|
@@ -10491,6 +11191,7 @@ export {
|
|
|
10491
11191
|
Switch,
|
|
10492
11192
|
Tabs,
|
|
10493
11193
|
Tag,
|
|
11194
|
+
TagSelect,
|
|
10494
11195
|
Textarea,
|
|
10495
11196
|
Tooltip,
|
|
10496
11197
|
Typography,
|