@camstack/ui-library 1.2.340 → 1.2.342
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
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.2.342] - 2026-10-28
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Option lists can group options under headings, and a dropdown can be opened and closed from outside
|
|
15
|
+
|
|
16
|
+
## [1.2.341] - 2026-10-28
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Account sign-in fields follow the vendor-login path of the hub login proxy
|
|
21
|
+
|
|
10
22
|
## [1.2.340] - 2026-10-27
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
@@ -13,6 +13,12 @@ export type OptionSelectOption = {
|
|
|
13
13
|
iconId?: string;
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
badge?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Heading this option is listed under. Options of one group are expected
|
|
18
|
+
* together (the list keeps its order); a heading is drawn where the group
|
|
19
|
+
* changes.
|
|
20
|
+
*/
|
|
21
|
+
group?: string;
|
|
16
22
|
};
|
|
17
23
|
/** Number of options at/above which search is enabled by default (unless creatable). */
|
|
18
24
|
export declare const OPTION_SELECT_SEARCH_MIN_OPTIONS = 8;
|
package/dist/index.cjs
CHANGED
|
@@ -12818,8 +12818,14 @@ function useDropdownContext() {
|
|
|
12818
12818
|
if (!ctx) throw new Error("Dropdown compound components must be used within <Dropdown>");
|
|
12819
12819
|
return ctx;
|
|
12820
12820
|
}
|
|
12821
|
-
function Dropdown({ children }) {
|
|
12822
|
-
const [
|
|
12821
|
+
function Dropdown({ children, open: controlledOpen, onOpenChange }) {
|
|
12822
|
+
const [innerOpen, setInnerOpen] = (0, react$1.useState)(false);
|
|
12823
|
+
const controlled = controlledOpen !== void 0 && onOpenChange !== void 0;
|
|
12824
|
+
const open = controlled ? controlledOpen : innerOpen;
|
|
12825
|
+
const setOpen = (0, react$1.useCallback)((next) => {
|
|
12826
|
+
if (controlled) onOpenChange(next);
|
|
12827
|
+
else setInnerOpen(next);
|
|
12828
|
+
}, [controlled, onOpenChange]);
|
|
12823
12829
|
const triggerId = (0, react$1.useId)();
|
|
12824
12830
|
const contentId = (0, react$1.useId)();
|
|
12825
12831
|
const triggerRef = (0, react$1.useRef)(null);
|
|
@@ -14010,7 +14016,13 @@ function OptionSelect(props) {
|
|
|
14010
14016
|
const checked = mode === "single" ? props.value === opt.value : props.value.includes(opt.value);
|
|
14011
14017
|
const blockedByMax = mode === "multi" && !checked && atMax === true;
|
|
14012
14018
|
const optionDisabled = opt.disabled === true || blockedByMax;
|
|
14013
|
-
|
|
14019
|
+
const previous = dropdownRows[i - 1];
|
|
14020
|
+
const previousGroup = previous !== void 0 && previous.kind === "option" ? previous.opt.group : void 0;
|
|
14021
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react$1.Fragment, { children: [opt.group !== void 0 && opt.group !== previousGroup ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
14022
|
+
role: "presentation",
|
|
14023
|
+
className: "px-2.5 pb-0.5 pt-1.5 text-[10px] font-medium uppercase tracking-wide text-foreground-subtle",
|
|
14024
|
+
children: opt.group
|
|
14025
|
+
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
14014
14026
|
type: "button",
|
|
14015
14027
|
role: "option",
|
|
14016
14028
|
"aria-selected": checked,
|
|
@@ -14038,7 +14050,7 @@ function OptionSelect(props) {
|
|
|
14038
14050
|
children: opt.badge
|
|
14039
14051
|
}) : null
|
|
14040
14052
|
]
|
|
14041
|
-
}, opt.value);
|
|
14053
|
+
})] }, opt.value);
|
|
14042
14054
|
}) });
|
|
14043
14055
|
const footerAddNewIndex = dropdownRows.length;
|
|
14044
14056
|
const fieldShowsChoice = mode === "single" && props.singleDisplay === "field" && selectedOptions.length > 0;
|
package/dist/index.js
CHANGED
|
@@ -12794,8 +12794,14 @@ function useDropdownContext() {
|
|
|
12794
12794
|
if (!ctx) throw new Error("Dropdown compound components must be used within <Dropdown>");
|
|
12795
12795
|
return ctx;
|
|
12796
12796
|
}
|
|
12797
|
-
function Dropdown({ children }) {
|
|
12798
|
-
const [
|
|
12797
|
+
function Dropdown({ children, open: controlledOpen, onOpenChange }) {
|
|
12798
|
+
const [innerOpen, setInnerOpen] = useState(false);
|
|
12799
|
+
const controlled = controlledOpen !== void 0 && onOpenChange !== void 0;
|
|
12800
|
+
const open = controlled ? controlledOpen : innerOpen;
|
|
12801
|
+
const setOpen = useCallback((next) => {
|
|
12802
|
+
if (controlled) onOpenChange(next);
|
|
12803
|
+
else setInnerOpen(next);
|
|
12804
|
+
}, [controlled, onOpenChange]);
|
|
12799
12805
|
const triggerId = useId();
|
|
12800
12806
|
const contentId = useId();
|
|
12801
12807
|
const triggerRef = useRef(null);
|
|
@@ -13986,7 +13992,13 @@ function OptionSelect(props) {
|
|
|
13986
13992
|
const checked = mode === "single" ? props.value === opt.value : props.value.includes(opt.value);
|
|
13987
13993
|
const blockedByMax = mode === "multi" && !checked && atMax === true;
|
|
13988
13994
|
const optionDisabled = opt.disabled === true || blockedByMax;
|
|
13989
|
-
|
|
13995
|
+
const previous = dropdownRows[i - 1];
|
|
13996
|
+
const previousGroup = previous !== void 0 && previous.kind === "option" ? previous.opt.group : void 0;
|
|
13997
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [opt.group !== void 0 && opt.group !== previousGroup ? /* @__PURE__ */ jsx("div", {
|
|
13998
|
+
role: "presentation",
|
|
13999
|
+
className: "px-2.5 pb-0.5 pt-1.5 text-[10px] font-medium uppercase tracking-wide text-foreground-subtle",
|
|
14000
|
+
children: opt.group
|
|
14001
|
+
}) : null, /* @__PURE__ */ jsxs("button", {
|
|
13990
14002
|
type: "button",
|
|
13991
14003
|
role: "option",
|
|
13992
14004
|
"aria-selected": checked,
|
|
@@ -14014,7 +14026,7 @@ function OptionSelect(props) {
|
|
|
14014
14026
|
children: opt.badge
|
|
14015
14027
|
}) : null
|
|
14016
14028
|
]
|
|
14017
|
-
}, opt.value);
|
|
14029
|
+
})] }, opt.value);
|
|
14018
14030
|
}) });
|
|
14019
14031
|
const footerAddNewIndex = dropdownRows.length;
|
|
14020
14032
|
const fieldShowsChoice = mode === "single" && props.singleDisplay === "field" && selectedOptions.length > 0;
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { type JSX, type ButtonHTMLAttributes, type HTMLAttributes, type ReactNode } from "react";
|
|
2
2
|
import { type LucideIcon } from "lucide-react";
|
|
3
|
-
export
|
|
4
|
-
children: ReactNode;
|
|
5
|
-
|
|
3
|
+
export interface DropdownProps {
|
|
4
|
+
readonly children: ReactNode;
|
|
5
|
+
/**
|
|
6
|
+
* Controlled open state. Give both `open` and `onOpenChange` to drive the menu
|
|
7
|
+
* from outside (a "{" typed in a field opens the variable list); give neither
|
|
8
|
+
* and the dropdown keeps its own state.
|
|
9
|
+
*/
|
|
10
|
+
readonly open?: boolean;
|
|
11
|
+
readonly onOpenChange?: (open: boolean) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function Dropdown({ children, open: controlledOpen, onOpenChange }: DropdownProps): JSX.Element | null;
|
|
6
14
|
export declare function DropdownTrigger({ children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>): JSX.Element | null;
|
|
7
15
|
interface DropdownContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
8
16
|
/** Horizontal alignment relative to the trigger. Default: 'start' (left-aligned). */
|