@choice-ui/react 2.0.1 → 2.0.2

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.
Files changed (36) hide show
  1. package/dist/components/button/dist/index.js +7 -0
  2. package/dist/components/checkbox/dist/index.d.ts +10 -1
  3. package/dist/components/checkbox/dist/index.js +49 -5
  4. package/dist/components/colors/dist/index.d.ts +39 -6
  5. package/dist/components/colors/src/color-image-paint/color-image-paint.js +2 -2
  6. package/dist/components/command/dist/index.d.ts +13 -0
  7. package/dist/components/dropdown/dist/index.d.ts +6 -0
  8. package/dist/components/dropdown/dist/index.js +20 -10
  9. package/dist/components/emoji-picker/dist/index.d.ts +29 -1
  10. package/dist/components/emoji-picker/dist/index.js +144 -42
  11. package/dist/components/form/src/adapters/range-adapter.js +2 -2
  12. package/dist/components/icon-button/dist/index.d.ts +1 -1
  13. package/dist/components/icon-button/dist/index.js +39 -0
  14. package/dist/components/list/dist/index.d.ts +1 -1
  15. package/dist/components/md-render/src/md-render.js +4 -0
  16. package/dist/components/md-render/src/types.d.ts +3 -0
  17. package/dist/components/menus/dist/index.d.ts +5 -0
  18. package/dist/components/menus/dist/index.js +32 -3
  19. package/dist/components/numeric-input/dist/index.d.ts +2 -0
  20. package/dist/components/numeric-input/dist/index.js +64 -24
  21. package/dist/components/numeric-input/src/hooks/use-input-interactions.d.ts +3 -1
  22. package/dist/components/numeric-input/src/hooks/use-input-interactions.js +7 -3
  23. package/dist/components/numeric-input/src/hooks/use-numeric-input.js +15 -4
  24. package/dist/components/numeric-input/src/numeric-input.js +5 -4
  25. package/dist/components/numeric-input/src/utils/value-comparator.js +1 -5
  26. package/dist/components/radio/dist/index.d.ts +9 -1
  27. package/dist/components/radio/dist/index.js +50 -6
  28. package/dist/components/range/dist/index.d.ts +276 -20
  29. package/dist/components/range/dist/index.js +1030 -602
  30. package/dist/components/scroll-area/dist/index.d.ts +4 -27
  31. package/dist/components/scroll-area/dist/index.js +96 -123
  32. package/dist/components/textarea/dist/index.js +3 -1
  33. package/dist/components/tooltip/dist/index.d.ts +2 -0
  34. package/dist/components/tooltip/dist/index.js +23 -5
  35. package/dist/components/virtual-select/dist/index.d.ts +48 -0
  36. package/package.json +19 -31
@@ -244,6 +244,13 @@ var buttonTv = tcv({
244
244
  loading: false,
245
245
  variant: "dark",
246
246
  class: { button: "active:bg-gray-600" }
247
+ },
248
+ {
249
+ disabled: false,
250
+ loading: false,
251
+ variant: "secondary",
252
+ active: false,
253
+ class: { button: "hover:bg-secondary-background" }
247
254
  }
248
255
  ],
249
256
  defaultVariants: {
@@ -1,6 +1,14 @@
1
1
  import { HTMLProps, ReactNode } from 'react';
2
2
  import * as react from 'react';
3
3
 
4
+ interface CheckboxIconProps extends Omit<HTMLProps<HTMLDivElement>, "children"> {
5
+ children?: ReactNode | ((props: {
6
+ value?: boolean;
7
+ mixed?: boolean;
8
+ }) => ReactNode);
9
+ }
10
+ declare const CheckboxIcon: react.MemoExoticComponent<react.ForwardRefExoticComponent<Omit<CheckboxIconProps, "ref"> & react.RefAttributes<HTMLDivElement>>>;
11
+
4
12
  interface CheckboxLabelProps extends Omit<HTMLProps<HTMLLabelElement>, "htmlFor" | "id" | "disabled"> {
5
13
  children: ReactNode;
6
14
  }
@@ -20,9 +28,10 @@ interface CheckboxType {
20
28
  (props: CheckboxProps & {
21
29
  ref?: React.Ref<HTMLInputElement>;
22
30
  }): JSX.Element;
31
+ Icon: typeof CheckboxIcon;
23
32
  Label: typeof CheckboxLabel;
24
33
  displayName?: string;
25
34
  }
26
35
  declare const Checkbox: CheckboxType;
27
36
 
28
- export { Checkbox, type CheckboxProps };
37
+ export { Checkbox, type CheckboxIconProps, type CheckboxLabelProps, type CheckboxProps };
@@ -1,5 +1,5 @@
1
1
  import { Indeterminate, Check } from "@choiceform/icons-react";
2
- import { memo, forwardRef, useId, createContext, useContext } from "react";
2
+ import { memo, forwardRef, useId, Children, isValidElement, createContext, useContext } from "react";
3
3
  import { useEventCallback } from "usehooks-ts";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { tcv, tcx } from "../../../shared/utils/tcx/tcx.js";
@@ -137,6 +137,38 @@ var checkboxTv = tcv({
137
137
  focused: false
138
138
  }
139
139
  });
140
+ var CheckboxIcon = memo(
141
+ forwardRef(function CheckboxIcon2(props, ref) {
142
+ const { className, children, ...rest } = props;
143
+ const { value, mixed, disabled, variant } = useCheckboxContext();
144
+ const tv = checkboxTv({
145
+ type: "checkbox",
146
+ variant,
147
+ disabled,
148
+ checked: value || mixed
149
+ });
150
+ const renderIcon = () => {
151
+ if (typeof children === "function") {
152
+ return children({ value, mixed });
153
+ }
154
+ if (children !== void 0) {
155
+ return children;
156
+ }
157
+ return mixed ? /* @__PURE__ */ jsx(Indeterminate, {}) : value ? /* @__PURE__ */ jsx(Check, {}) : null;
158
+ };
159
+ return /* @__PURE__ */ jsx(
160
+ "div",
161
+ {
162
+ ref,
163
+ className: tcx(tv.box(), className),
164
+ "data-active": value,
165
+ ...rest,
166
+ children: renderIcon()
167
+ }
168
+ );
169
+ })
170
+ );
171
+ CheckboxIcon.displayName = "Checkbox.Icon";
140
172
  var CheckboxLabel = memo(
141
173
  forwardRef(function CheckboxLabel2(props, ref) {
142
174
  const { children, className, ...rest } = props;
@@ -195,12 +227,23 @@ var CheckboxBase = forwardRef(function Checkbox(props, ref) {
195
227
  }
196
228
  onKeyDown == null ? void 0 : onKeyDown(e);
197
229
  });
230
+ const isIconElement = (child) => {
231
+ var _a;
232
+ return isValidElement(child) && (child.type === CheckboxIcon || ((_a = child.type) == null ? void 0 : _a.displayName) === "Checkbox.Icon");
233
+ };
234
+ const childArray = Children.toArray(children);
235
+ const iconChild = childArray.find(isIconElement);
236
+ const otherChildren = childArray.filter((child) => !isIconElement(child));
198
237
  const renderChildren = () => {
199
- if (typeof children === "string" || typeof children === "number") {
200
- return /* @__PURE__ */ jsx(CheckboxLabel, { children });
238
+ if (otherChildren.length === 1) {
239
+ const child = otherChildren[0];
240
+ if (typeof child === "string" || typeof child === "number") {
241
+ return /* @__PURE__ */ jsx(CheckboxLabel, { children: child });
242
+ }
201
243
  }
202
- return children;
244
+ return otherChildren;
203
245
  };
246
+ const renderDefaultIcon = () => /* @__PURE__ */ jsx("div", { className: tv.box(), children: mixed ? /* @__PURE__ */ jsx(Indeterminate, {}) : value ? /* @__PURE__ */ jsx(Check, {}) : null });
204
247
  return /* @__PURE__ */ jsx(
205
248
  CheckboxContext.Provider,
206
249
  {
@@ -234,7 +277,7 @@ var CheckboxBase = forwardRef(function Checkbox(props, ref) {
234
277
  ...rest
235
278
  }
236
279
  ),
237
- /* @__PURE__ */ jsx("div", { className: tv.box(), children: mixed ? /* @__PURE__ */ jsx(Indeterminate, {}) : value ? /* @__PURE__ */ jsx(Check, {}) : null })
280
+ iconChild ?? renderDefaultIcon()
238
281
  ] }),
239
282
  renderChildren()
240
283
  ] })
@@ -243,6 +286,7 @@ var CheckboxBase = forwardRef(function Checkbox(props, ref) {
243
286
  });
244
287
  var MemoizedCheckbox = memo(CheckboxBase);
245
288
  var Checkbox2 = MemoizedCheckbox;
289
+ Checkbox2.Icon = CheckboxIcon;
246
290
  Checkbox2.Label = CheckboxLabel;
247
291
  Checkbox2.displayName = "Checkbox";
248
292
  export {
@@ -452,8 +452,37 @@ interface ColorAreaProps {
452
452
  }
453
453
  declare const ColorArea: react.MemoExoticComponent<react.ForwardRefExoticComponent<ColorAreaProps & react.RefAttributes<HTMLDivElement>>>;
454
454
 
455
+ interface ColorSliderThumbProps {
456
+ className?: string;
457
+ size?: number;
458
+ }
459
+ declare function ColorSliderThumb(props: ColorSliderThumbProps): react_jsx_runtime.JSX.Element;
460
+ declare namespace ColorSliderThumb {
461
+ var displayName: string;
462
+ }
463
+
464
+ interface ColorSliderTrackProps {
465
+ className?: string;
466
+ children?: React.ReactNode;
467
+ /**
468
+ * Height of the track in pixels.
469
+ * This prop is extracted by the parent ColorSlider and passed via context.
470
+ */
471
+ height?: number;
472
+ }
473
+ /**
474
+ * ColorSliderTrack - The track background of the color slider.
475
+ * Renders the gradient background based on slider type (hue, alpha, etc.)
476
+ * Can contain custom children for additional visual elements.
477
+ */
478
+ declare function ColorSliderTrack(props: ColorSliderTrackProps): react_jsx_runtime.JSX.Element;
479
+ declare namespace ColorSliderTrack {
480
+ var displayName: string;
481
+ }
482
+
455
483
  interface ColorSliderProps {
456
484
  backgroundStyle?: CSSProperties;
485
+ children?: React.ReactNode;
457
486
  className?: string;
458
487
  disabled?: boolean;
459
488
  hue?: number;
@@ -461,14 +490,18 @@ interface ColorSliderProps {
461
490
  onChangeEnd?: () => void;
462
491
  onChangeStart?: () => void;
463
492
  position: number;
464
- thumbSize?: number;
465
- trackSize?: {
466
- height?: number;
467
- width?: number;
468
- };
469
493
  type: PickerSliderType;
494
+ /**
495
+ * Width of the slider track in pixels.
496
+ * If not provided (undefined or false), the width will be auto-calculated from the container.
497
+ */
498
+ width?: number | boolean;
499
+ }
500
+ interface ColorSliderComponent extends React.MemoExoticComponent<React.ForwardRefExoticComponent<ColorSliderProps & React.RefAttributes<HTMLDivElement>>> {
501
+ Thumb: typeof ColorSliderThumb;
502
+ Track: typeof ColorSliderTrack;
470
503
  }
471
- declare const ColorSlider: react.MemoExoticComponent<react.ForwardRefExoticComponent<ColorSliderProps & react.RefAttributes<HTMLDivElement>>>;
504
+ declare const ColorSlider: ColorSliderComponent;
472
505
 
473
506
  interface ColorSwatchProps extends Omit<HTMLProps<HTMLDivElement>, "color"> {
474
507
  alpha?: number;
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { Button } from "../../../button/dist/index.js";
3
- import { Range } from "../../../range/dist/index.js";
3
+ import { Range as Range2 } from "../../../range/dist/index.js";
4
4
  import React__default, { memo, useState, useRef, useMemo, useEffect, useCallback } from "react";
5
5
  import { useEventCallback } from "usehooks-ts";
6
6
  import { ColorImageToolbar } from "./color-image-toolbar.js";
@@ -209,7 +209,7 @@ const ColorImagePaint = memo(function ColorImagePaint2(props) {
209
209
  return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
210
210
  /* @__PURE__ */ jsx("span", { className: styles.adjustLabel(), children: (_a2 = features == null ? void 0 : features.labels) == null ? void 0 : _a2[filterName] }),
211
211
  /* @__PURE__ */ jsx(
212
- Range,
212
+ Range2,
213
213
  {
214
214
  min: -100,
215
215
  max: 100,
@@ -43,6 +43,10 @@ interface CommandItemProps extends Omit<HTMLProps<HTMLDivElement>, "onSelect"> {
43
43
  keywords?: string[];
44
44
  onSelect?: (value: string) => void;
45
45
  prefixElement?: ReactNode;
46
+ /**
47
+ * When true, this item will be set as the selected item and scrolled into view.
48
+ */
49
+ selected?: boolean;
46
50
  shortcut?: {
47
51
  keys?: ReactNode;
48
52
  modifier?: KbdKey | KbdKey[] | undefined;
@@ -54,6 +58,9 @@ interface CommandItemProps extends Omit<HTMLProps<HTMLDivElement>, "onSelect"> {
54
58
  interface CommandListProps extends ScrollAreaProps {
55
59
  children: React.ReactNode;
56
60
  className?: string;
61
+ classNames?: {
62
+ content?: string;
63
+ };
57
64
  label?: string;
58
65
  }
59
66
 
@@ -106,6 +113,11 @@ interface CommandProps extends Omit<react__default.HTMLAttributes<HTMLDivElement
106
113
  * Event handler called when the selected item of the menu changes.
107
114
  */
108
115
  onChange?: (value: string) => void;
116
+ /**
117
+ * Optionally set to `true` to enable selection mode.
118
+ * When enabled, items with `selected` prop will be scrolled into view on mount.
119
+ */
120
+ selection?: boolean;
109
121
  /**
110
122
  * Optionally set to `false` to turn off the automatic filtering and sorting.
111
123
  * If `false`, you must conditionally render valid items based on the search query yourself.
@@ -140,6 +152,7 @@ type Context = {
140
152
  labelId: string;
141
153
  listId: string;
142
154
  listInnerRef: react__default.MutableRefObject<HTMLDivElement | null>;
155
+ selection?: boolean;
143
156
  size?: "default" | "large";
144
157
  store: Store;
145
158
  value: (id: string, value?: string, keywords?: string[]) => void;
@@ -7,6 +7,12 @@ interface DropdownProps {
7
7
  * @default true
8
8
  */
9
9
  autoSelectFirstItem?: boolean;
10
+ /**
11
+ * Whether to avoid collisions by flipping or shifting the dropdown position.
12
+ * When false, the dropdown will strictly follow the placement direction.
13
+ * @default true
14
+ */
15
+ avoidCollisions?: boolean;
10
16
  children?: React.ReactNode;
11
17
  disabledNested?: boolean;
12
18
  focusManagerProps?: Partial<FloatingFocusManagerProps>;
@@ -13,6 +13,7 @@ var DropdownComponent = memo(function DropdownComponent2(props) {
13
13
  const {
14
14
  children,
15
15
  autoSelectFirstItem = true,
16
+ avoidCollisions = true,
16
17
  disabledNested = false,
17
18
  offset: offsetDistance = DEFAULT_OFFSET,
18
19
  placement = "bottom-start",
@@ -53,7 +54,7 @@ var DropdownComponent = memo(function DropdownComponent2(props) {
53
54
  }
54
55
  onOpenChange == null ? void 0 : onOpenChange(newOpen);
55
56
  });
56
- const { nodeId, item, isNested } = useMenuTree({
57
+ const { nodeId, item, isNested, tree } = useMenuTree({
57
58
  disabledNested,
58
59
  handleOpenChange,
59
60
  isControlledOpen
@@ -77,11 +78,14 @@ var DropdownComponent = memo(function DropdownComponent2(props) {
77
78
  });
78
79
  });
79
80
  const lastPositionRef = useRef(null);
80
- const middleware = useMemo(
81
- () => [
82
- offset({ mainAxis: isNested ? 10 : offsetDistance, alignmentAxis: isNested ? -4 : 0 }),
83
- flip(),
84
- shift(),
81
+ const middleware = useMemo(() => {
82
+ const baseMiddleware = [
83
+ offset({ mainAxis: isNested ? 10 : offsetDistance, alignmentAxis: isNested ? -4 : 0 })
84
+ ];
85
+ if (avoidCollisions) {
86
+ baseMiddleware.push(flip(), shift());
87
+ }
88
+ baseMiddleware.push(
85
89
  size({
86
90
  padding: 4,
87
91
  apply({ elements, availableHeight, rects }) {
@@ -104,9 +108,9 @@ var DropdownComponent = memo(function DropdownComponent2(props) {
104
108
  }
105
109
  }
106
110
  })
107
- ],
108
- [isNested, offsetDistance, matchTriggerWidth, scrollRef]
109
- );
111
+ );
112
+ return baseMiddleware;
113
+ }, [isNested, offsetDistance, matchTriggerWidth, scrollRef, avoidCollisions]);
110
114
  const { refs, floatingStyles, context, isPositioned } = useFloating({
111
115
  nodeId,
112
116
  open: isControlledOpen,
@@ -165,11 +169,17 @@ var DropdownComponent = memo(function DropdownComponent2(props) {
165
169
  bubbles: true,
166
170
  escapeKey: true
167
171
  });
172
+ const handleNavigate = useEventCallback((index) => {
173
+ setActiveIndex(index);
174
+ if (tree && index !== null) {
175
+ tree.events.emit("navigate", { nodeId, index });
176
+ }
177
+ });
168
178
  const listNavigation = useListNavigation(context, {
169
179
  listRef: elementsRef,
170
180
  activeIndex,
171
181
  nested: isNested,
172
- onNavigate: setActiveIndex,
182
+ onNavigate: handleNavigate,
173
183
  loop: true
174
184
  });
175
185
  const typeahead = useTypeahead(context, {
@@ -15,12 +15,24 @@ type VirtualItem = {
15
15
  emojis: EmojiData[];
16
16
  type: "emojis";
17
17
  };
18
+ interface CategoryNames {
19
+ activities: string;
20
+ animalsNature: string;
21
+ flags: string;
22
+ foodDrink: string;
23
+ frequentlyUsed: string;
24
+ objects: string;
25
+ smileysPeople: string;
26
+ symbols: string;
27
+ travelPlaces: string;
28
+ }
18
29
  interface UseEmojiDataProps {
30
+ categoryNames?: CategoryNames;
19
31
  columns: number;
20
32
  searchQuery: string;
21
33
  showFrequentlyUsed: boolean;
22
34
  }
23
- declare function useEmojiData({ searchQuery, columns, showFrequentlyUsed }: UseEmojiDataProps): {
35
+ declare function useEmojiData({ searchQuery, columns, showFrequentlyUsed, categoryNames, }: UseEmojiDataProps): {
24
36
  categorizedData: VirtualItem[];
25
37
  categoryIndexMap: Map<EmojiCategory, number>;
26
38
  searchResults: {
@@ -52,6 +64,22 @@ interface EmojiPickerProps {
52
64
  showFooter?: boolean;
53
65
  value?: EmojiData | null;
54
66
  variant?: "default" | "dark" | "light";
67
+ i18n?: {
68
+ noEmojisFoundTitle?: string;
69
+ noEmojisFoundDescription?: string;
70
+ footerPickAnEmoji?: string;
71
+ categories?: {
72
+ frequentlyUsed: string;
73
+ smileysPeople: string;
74
+ animalsNature: string;
75
+ foodDrink: string;
76
+ travelPlaces: string;
77
+ activities: string;
78
+ objects: string;
79
+ symbols: string;
80
+ flags: string;
81
+ };
82
+ };
55
83
  }
56
84
  declare const EmojiPicker: React.NamedExoticComponent<EmojiPickerProps>;
57
85