@choice-ui/react 2.0.0 → 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 (53) hide show
  1. package/dist/components/button/dist/index.d.ts +2 -9
  2. package/dist/components/button/dist/index.js +45 -19
  3. package/dist/components/checkbox/dist/index.d.ts +10 -1
  4. package/dist/components/checkbox/dist/index.js +49 -5
  5. package/dist/components/code-block/dist/index.d.ts +11 -14
  6. package/dist/components/code-block/dist/index.js +120 -93
  7. package/dist/components/colors/dist/index.d.ts +39 -6
  8. package/dist/components/colors/src/color-image-paint/color-image-paint.js +2 -2
  9. package/dist/components/dropdown/dist/index.d.ts +6 -0
  10. package/dist/components/dropdown/dist/index.js +20 -10
  11. package/dist/components/emoji-picker/dist/index.d.ts +30 -1
  12. package/dist/components/emoji-picker/dist/index.js +148 -44
  13. package/dist/components/form/src/adapters/range-adapter.js +2 -2
  14. package/dist/components/icon-button/dist/index.d.ts +1 -1
  15. package/dist/components/icon-button/dist/index.js +39 -0
  16. package/dist/components/list/dist/index.d.ts +1 -1
  17. package/dist/components/md-render/dist/index.d.ts +2 -1
  18. package/dist/components/md-render/dist/index.js +5 -9
  19. package/dist/components/md-render/src/components/markdown-block.d.ts +3 -0
  20. package/dist/components/md-render/src/md-render.js +4 -0
  21. package/dist/components/md-render/src/types.d.ts +3 -0
  22. package/dist/components/menus/dist/index.d.ts +5 -0
  23. package/dist/components/menus/dist/index.js +32 -3
  24. package/dist/components/modal/dist/index.js +2 -2
  25. package/dist/components/notifications/dist/index.d.ts +1 -5
  26. package/dist/components/numeric-input/dist/index.d.ts +27 -10
  27. package/dist/components/numeric-input/dist/index.js +132 -34
  28. package/dist/components/numeric-input/src/hooks/use-input-interactions.d.ts +3 -1
  29. package/dist/components/numeric-input/src/hooks/use-input-interactions.js +7 -3
  30. package/dist/components/numeric-input/src/hooks/use-numeric-input.js +15 -4
  31. package/dist/components/numeric-input/src/numeric-input.js +5 -4
  32. package/dist/components/numeric-input/src/utils/value-comparator.js +1 -5
  33. package/dist/components/panel/dist/index.d.ts +16 -16
  34. package/dist/components/picture-preview/dist/index.d.ts +5 -0
  35. package/dist/components/picture-preview/dist/index.js +287 -140
  36. package/dist/components/popover/dist/index.d.ts +5 -0
  37. package/dist/components/popover/dist/index.js +21 -2
  38. package/dist/components/radio/dist/index.d.ts +9 -1
  39. package/dist/components/radio/dist/index.js +50 -6
  40. package/dist/components/range/dist/index.d.ts +276 -20
  41. package/dist/components/range/dist/index.js +1030 -602
  42. package/dist/components/scroll-area/dist/index.d.ts +4 -27
  43. package/dist/components/scroll-area/dist/index.js +96 -123
  44. package/dist/components/separator/dist/index.d.ts +1 -8
  45. package/dist/components/splitter/dist/index.d.ts +1 -1
  46. package/dist/components/text-field/dist/index.d.ts +2 -3
  47. package/dist/components/text-field/dist/index.js +4 -19
  48. package/dist/components/textarea/dist/index.js +3 -1
  49. package/dist/components/toast/dist/index.d.ts +274 -0
  50. package/dist/components/tooltip/dist/index.d.ts +2 -0
  51. package/dist/components/tooltip/dist/index.js +23 -5
  52. package/dist/components/virtual-select/dist/index.d.ts +48 -0
  53. package/package.json +3 -3
@@ -141,7 +141,7 @@ var emojiFooterTv = tcv({
141
141
  var emojiEmptyTv = tcv({
142
142
  slots: {
143
143
  container: "flex h-32 flex-col items-center justify-center p-4 text-center",
144
- title: "text-heading-display",
144
+ title: "text-body-large-strong",
145
145
  description: "mt-2 w-32"
146
146
  },
147
147
  variants: {
@@ -179,13 +179,20 @@ var EmojiCategoryHeader = forwardRef(
179
179
  );
180
180
  }
181
181
  );
182
- function EmojiFooter({ hoveredEmoji, selectedEmoji, variant = "dark" }) {
182
+ var EmojiFooter = memo(function EmojiFooter2({
183
+ hoveredEmoji,
184
+ selectedEmoji,
185
+ variant = "dark",
186
+ i18n = {
187
+ pickAnEmoji: "Pick an emoji..."
188
+ }
189
+ }) {
183
190
  var _a, _b;
184
191
  const tv = emojiFooterTv({ variant });
185
192
  return /* @__PURE__ */ jsxs("div", { className: tv.footer(), children: [
186
193
  /* @__PURE__ */ jsx("div", { className: tv.emojiPreview(), children: ((_a = hoveredEmoji || selectedEmoji) == null ? void 0 : _a.emoji) || /* @__PURE__ */ jsx("div", { className: tv.emojiPreviewEmpty() }) }),
187
194
  /* @__PURE__ */ jsxs("div", { className: tv.emojiInfo(), children: [
188
- /* @__PURE__ */ jsx("div", { className: tv.emojiName(), children: (hoveredEmoji == null ? void 0 : hoveredEmoji.name) || (selectedEmoji == null ? void 0 : selectedEmoji.name) || "Pick an emoji..." }),
195
+ /* @__PURE__ */ jsx("div", { className: tv.emojiName(), children: (hoveredEmoji == null ? void 0 : hoveredEmoji.name) || (selectedEmoji == null ? void 0 : selectedEmoji.name) || i18n.pickAnEmoji }),
189
196
  hoveredEmoji || selectedEmoji ? /* @__PURE__ */ jsxs("div", { className: tv.emojiCode(), children: [
190
197
  ":",
191
198
  (_b = hoveredEmoji || selectedEmoji) == null ? void 0 : _b.nameUrl,
@@ -193,7 +200,7 @@ function EmojiFooter({ hoveredEmoji, selectedEmoji, variant = "dark" }) {
193
200
  ] }) : /* @__PURE__ */ jsx(Fragment, {})
194
201
  ] })
195
202
  ] });
196
- }
203
+ });
197
204
  var EmojiItem = memo(function EmojiItem2(props) {
198
205
  const { emoji, onSelect, onHover, selected = false, variant = "dark" } = props;
199
206
  return /* @__PURE__ */ jsx(
@@ -209,11 +216,17 @@ var EmojiItem = memo(function EmojiItem2(props) {
209
216
  }
210
217
  );
211
218
  });
212
- var EmojiEmpty = memo(function EmojiEmpty2({ variant = "dark" }) {
219
+ var EmojiEmpty = memo(function EmojiEmpty2({
220
+ variant = "dark",
221
+ i18n = {
222
+ title: "No emoji found",
223
+ description: "You can search for an emoji by name or use the search bar to find it."
224
+ }
225
+ }) {
213
226
  const tv = emojiEmptyTv({ variant });
214
227
  return /* @__PURE__ */ jsxs("div", { className: tv.container(), children: [
215
- /* @__PURE__ */ jsx("div", { className: tv.title(), children: "No emoji found" }),
216
- /* @__PURE__ */ jsx("p", { className: tv.description(), children: "You can search for an emoji by name or use the search bar to find it." })
228
+ /* @__PURE__ */ jsx("div", { className: tv.title(), children: i18n.title }),
229
+ /* @__PURE__ */ jsx("p", { className: tv.description(), children: i18n.description })
217
230
  ] });
218
231
  });
219
232
  var emojis = [
@@ -11727,15 +11740,15 @@ var emojis = [
11727
11740
  }
11728
11741
  ];
11729
11742
  var categories = [
11730
- { id: "frequently_used", name: "Frequently used" },
11731
- { id: "smileys_people", name: "Smileys & People", range: [1, 460] },
11732
- { id: "animals_nature", name: "Animals & Nature", range: [465, 591] },
11733
- { id: "food_drink", name: "Food & Drink", range: [592, 712] },
11734
- { id: "travel_places", name: "Travel & Places", range: [713, 922] },
11735
- { id: "activities", name: "Activities", range: [923, 1001] },
11736
- { id: "objects", name: "Objects", range: [1002, 1234] },
11737
- { id: "symbols", name: "Symbols", range: [1235, 1451] },
11738
- { id: "flags", name: "Flags", range: [1452, 1719] }
11743
+ { id: "frequently_used" },
11744
+ { id: "smileys_people", range: [1, 460] },
11745
+ { id: "animals_nature", range: [465, 591] },
11746
+ { id: "food_drink", range: [592, 712] },
11747
+ { id: "travel_places", range: [713, 922] },
11748
+ { id: "activities", range: [923, 1001] },
11749
+ { id: "objects", range: [1002, 1234] },
11750
+ { id: "symbols", range: [1235, 1451] },
11751
+ { id: "flags", range: [1452, 1719] }
11739
11752
  ];
11740
11753
  var STORAGE_KEY = "emoji-picker-frequently-used";
11741
11754
  function getEmojiCategory(id) {
@@ -11769,7 +11782,34 @@ function saveFrequentlyUsedEmoji(emojiId) {
11769
11782
  } catch {
11770
11783
  }
11771
11784
  }
11772
- function useEmojiData({ searchQuery, columns, showFrequentlyUsed }) {
11785
+ var defaultCategoryNames = {
11786
+ frequentlyUsed: "Frequently used",
11787
+ smileysPeople: "Smileys & People",
11788
+ animalsNature: "Animals & Nature",
11789
+ foodDrink: "Food & Drink",
11790
+ travelPlaces: "Travel & Places",
11791
+ activities: "Activities",
11792
+ objects: "Objects",
11793
+ symbols: "Symbols",
11794
+ flags: "Flags"
11795
+ };
11796
+ var categoryIdToI18nKey = {
11797
+ frequently_used: "frequentlyUsed",
11798
+ smileys_people: "smileysPeople",
11799
+ animals_nature: "animalsNature",
11800
+ food_drink: "foodDrink",
11801
+ travel_places: "travelPlaces",
11802
+ activities: "activities",
11803
+ objects: "objects",
11804
+ symbols: "symbols",
11805
+ flags: "flags"
11806
+ };
11807
+ function useEmojiData({
11808
+ searchQuery,
11809
+ columns,
11810
+ showFrequentlyUsed,
11811
+ categoryNames = defaultCategoryNames
11812
+ }) {
11773
11813
  const [frequentlyUsed, setFrequentlyUsed] = useState([]);
11774
11814
  useEffect(() => {
11775
11815
  if (showFrequentlyUsed) {
@@ -11799,7 +11839,7 @@ function useEmojiData({ searchQuery, columns, showFrequentlyUsed }) {
11799
11839
  items.push({
11800
11840
  type: "header",
11801
11841
  category: "frequently_used",
11802
- title: "Frequently used"
11842
+ title: categoryNames.frequentlyUsed
11803
11843
  });
11804
11844
  for (let i = 0; i < frequentlyUsed.length; i += columns) {
11805
11845
  items.push({
@@ -11814,10 +11854,11 @@ function useEmojiData({ searchQuery, columns, showFrequentlyUsed }) {
11814
11854
  (emoji) => emoji.id >= category.range[0] && emoji.id <= category.range[1]
11815
11855
  );
11816
11856
  if (categoryEmojis.length > 0) {
11857
+ const i18nKey = categoryIdToI18nKey[category.id];
11817
11858
  items.push({
11818
11859
  type: "header",
11819
11860
  category: category.id,
11820
- title: category.name
11861
+ title: i18nKey ? categoryNames[i18nKey] : category.id
11821
11862
  });
11822
11863
  for (let i = 0; i < categoryEmojis.length; i += columns) {
11823
11864
  items.push({
@@ -11828,7 +11869,7 @@ function useEmojiData({ searchQuery, columns, showFrequentlyUsed }) {
11828
11869
  }
11829
11870
  });
11830
11871
  return items;
11831
- }, [searchQuery, searchResults, frequentlyUsed, columns, showFrequentlyUsed]);
11872
+ }, [searchQuery, searchResults, frequentlyUsed, columns, showFrequentlyUsed, categoryNames]);
11832
11873
  const categoryIndexMap = useMemo(() => {
11833
11874
  const map = /* @__PURE__ */ new Map();
11834
11875
  categorizedData.forEach((item, index) => {
@@ -11884,6 +11925,8 @@ function useEmojiScroll({
11884
11925
  const [currentVisibleCategory, setCurrentVisibleCategory] = useState("frequently_used");
11885
11926
  const isScrollingToTarget = useRef(false);
11886
11927
  const isInternalUpdate = useRef(false);
11928
+ const scrollingTimeoutRef = useRef(null);
11929
+ const internalUpdateTimeoutRef = useRef(null);
11887
11930
  const virtualizer = useVirtualizer({
11888
11931
  count: categorizedData.length,
11889
11932
  getScrollElement: () => scrollRef.current,
@@ -11948,7 +11991,10 @@ function useEmojiScroll({
11948
11991
  align: "start",
11949
11992
  behavior: "auto"
11950
11993
  });
11951
- setTimeout(() => {
11994
+ if (scrollingTimeoutRef.current) {
11995
+ clearTimeout(scrollingTimeoutRef.current);
11996
+ }
11997
+ scrollingTimeoutRef.current = setTimeout(() => {
11952
11998
  isScrollingToTarget.current = false;
11953
11999
  }, 100);
11954
12000
  }
@@ -11961,17 +12007,33 @@ function useEmojiScroll({
11961
12007
  align: "center",
11962
12008
  behavior: "auto"
11963
12009
  });
11964
- setTimeout(() => {
12010
+ if (scrollingTimeoutRef.current) {
12011
+ clearTimeout(scrollingTimeoutRef.current);
12012
+ }
12013
+ scrollingTimeoutRef.current = setTimeout(() => {
11965
12014
  isScrollingToTarget.current = false;
11966
12015
  }, 100);
11967
12016
  }
11968
12017
  });
11969
12018
  const markInternalUpdate = useEventCallback(() => {
11970
12019
  isInternalUpdate.current = true;
11971
- setTimeout(() => {
12020
+ if (internalUpdateTimeoutRef.current) {
12021
+ clearTimeout(internalUpdateTimeoutRef.current);
12022
+ }
12023
+ internalUpdateTimeoutRef.current = setTimeout(() => {
11972
12024
  isInternalUpdate.current = false;
11973
12025
  }, 50);
11974
12026
  });
12027
+ useEffect(() => {
12028
+ return () => {
12029
+ if (scrollingTimeoutRef.current) {
12030
+ clearTimeout(scrollingTimeoutRef.current);
12031
+ }
12032
+ if (internalUpdateTimeoutRef.current) {
12033
+ clearTimeout(internalUpdateTimeoutRef.current);
12034
+ }
12035
+ };
12036
+ }, []);
11975
12037
  useEffect(() => {
11976
12038
  if (value && !searchQuery.trim() && !isInternalUpdate.current) {
11977
12039
  scrollToEmoji(value);
@@ -11996,17 +12058,6 @@ function useEmojiScroll({
11996
12058
  PADDING
11997
12059
  };
11998
12060
  }
11999
- var categoriesWithIcons = [
12000
- { id: "frequently_used", name: "Frequently used", icon: /* @__PURE__ */ jsx(EmojiFrequentlyUsed, {}) },
12001
- { id: "smileys_people", name: "Smileys & People", icon: /* @__PURE__ */ jsx(EmojiSmileysPeople, {}) },
12002
- { id: "animals_nature", name: "Animals & Nature", icon: /* @__PURE__ */ jsx(EmojiAnimalsNature, {}) },
12003
- { id: "food_drink", name: "Food & Drink", icon: /* @__PURE__ */ jsx(EmojiFoodDrink, {}) },
12004
- { id: "travel_places", name: "Travel & Places", icon: /* @__PURE__ */ jsx(EmojiTravelPlaces, {}) },
12005
- { id: "activities", name: "Activities", icon: /* @__PURE__ */ jsx(EmojiActivity, {}) },
12006
- { id: "objects", name: "Objects", icon: /* @__PURE__ */ jsx(EmojiObjects, {}) },
12007
- { id: "symbols", name: "Symbols", icon: /* @__PURE__ */ jsx(EmojiSymbols, {}) },
12008
- { id: "flags", name: "Flags", icon: /* @__PURE__ */ jsx(EmojiFlags, {}) }
12009
- ];
12010
12061
  var EmojiPicker = memo(function EmojiPicker2({
12011
12062
  value,
12012
12063
  onChange,
@@ -12017,12 +12068,51 @@ var EmojiPicker = memo(function EmojiPicker2({
12017
12068
  showCategories = true,
12018
12069
  showFrequentlyUsed = true,
12019
12070
  showSearch = true,
12071
+ showFooter = true,
12020
12072
  children,
12021
- variant = "dark"
12073
+ variant = "dark",
12074
+ i18n = {
12075
+ noEmojisFoundTitle: "No emoji found",
12076
+ noEmojisFoundDescription: "You can search for an emoji by name or use the search bar to find it.",
12077
+ footerPickAnEmoji: "Pick an emoji...",
12078
+ categories: {
12079
+ frequentlyUsed: "Frequently used",
12080
+ smileysPeople: "Smileys & People",
12081
+ animalsNature: "Animals & Nature",
12082
+ foodDrink: "Food & Drink",
12083
+ travelPlaces: "Travel & Places",
12084
+ activities: "Activities",
12085
+ objects: "Objects",
12086
+ symbols: "Symbols",
12087
+ flags: "Flags"
12088
+ }
12089
+ }
12022
12090
  }) {
12023
12091
  const [searchQuery, setSearchQuery] = useState("");
12024
12092
  const [hoveredEmoji, setHoveredEmoji] = useState(null);
12093
+ const safeColumns = Math.max(1, columns);
12025
12094
  const tv = emojiTv({ variant });
12095
+ const categoriesWithIcons = useMemo(
12096
+ () => {
12097
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
12098
+ return [
12099
+ {
12100
+ id: "frequently_used",
12101
+ name: (_a = i18n.categories) == null ? void 0 : _a.frequentlyUsed,
12102
+ icon: /* @__PURE__ */ jsx(EmojiFrequentlyUsed, {})
12103
+ },
12104
+ { id: "smileys_people", name: (_b = i18n.categories) == null ? void 0 : _b.smileysPeople, icon: /* @__PURE__ */ jsx(EmojiSmileysPeople, {}) },
12105
+ { id: "animals_nature", name: (_c = i18n.categories) == null ? void 0 : _c.animalsNature, icon: /* @__PURE__ */ jsx(EmojiAnimalsNature, {}) },
12106
+ { id: "food_drink", name: (_d = i18n.categories) == null ? void 0 : _d.foodDrink, icon: /* @__PURE__ */ jsx(EmojiFoodDrink, {}) },
12107
+ { id: "travel_places", name: (_e = i18n.categories) == null ? void 0 : _e.travelPlaces, icon: /* @__PURE__ */ jsx(EmojiTravelPlaces, {}) },
12108
+ { id: "activities", name: (_f = i18n.categories) == null ? void 0 : _f.activities, icon: /* @__PURE__ */ jsx(EmojiActivity, {}) },
12109
+ { id: "objects", name: (_g = i18n.categories) == null ? void 0 : _g.objects, icon: /* @__PURE__ */ jsx(EmojiObjects, {}) },
12110
+ { id: "symbols", name: (_h = i18n.categories) == null ? void 0 : _h.symbols, icon: /* @__PURE__ */ jsx(EmojiSymbols, {}) },
12111
+ { id: "flags", name: (_i = i18n.categories) == null ? void 0 : _i.flags, icon: /* @__PURE__ */ jsx(EmojiFlags, {}) }
12112
+ ];
12113
+ },
12114
+ [i18n.categories]
12115
+ );
12026
12116
  const {
12027
12117
  categorizedData,
12028
12118
  categoryIndexMap,
@@ -12030,8 +12120,9 @@ var EmojiPicker = memo(function EmojiPicker2({
12030
12120
  findEmojiPosition
12031
12121
  } = useEmojiData({
12032
12122
  searchQuery,
12033
- columns,
12034
- showFrequentlyUsed
12123
+ columns: safeColumns,
12124
+ showFrequentlyUsed,
12125
+ categoryNames: i18n.categories
12035
12126
  });
12036
12127
  const {
12037
12128
  scrollRef,
@@ -12047,7 +12138,7 @@ var EmojiPicker = memo(function EmojiPicker2({
12047
12138
  findEmojiPosition,
12048
12139
  searchQuery,
12049
12140
  value,
12050
- columns
12141
+ columns: safeColumns
12051
12142
  });
12052
12143
  const availableCategories = useMemo(() => {
12053
12144
  return categoriesWithIcons.filter((category) => {
@@ -12056,13 +12147,14 @@ var EmojiPicker = memo(function EmojiPicker2({
12056
12147
  }
12057
12148
  return true;
12058
12149
  });
12059
- }, [showFrequentlyUsed]);
12150
+ }, [categoriesWithIcons, showFrequentlyUsed]);
12060
12151
  const handleEmojiSelect = useEventCallback((emoji) => {
12061
12152
  markInternalUpdate();
12062
12153
  addToFrequentlyUsed(emoji.id);
12063
12154
  onChange == null ? void 0 : onChange(emoji);
12064
12155
  });
12065
12156
  const handleEmojiHover = useEventCallback((emoji) => {
12157
+ if (!showFooter) return;
12066
12158
  setHoveredEmoji(emoji);
12067
12159
  });
12068
12160
  const handleCategoryClick = useEventCallback((category) => {
@@ -12071,7 +12163,7 @@ var EmojiPicker = memo(function EmojiPicker2({
12071
12163
  const rootStyle = {
12072
12164
  "--emoji-height": `${height}px`,
12073
12165
  "--emoji-padding": `${PADDING2}px`,
12074
- "--emoji-columns": `${columns}`
12166
+ "--emoji-columns": `${safeColumns}`
12075
12167
  };
12076
12168
  return /* @__PURE__ */ jsxs(
12077
12169
  "div",
@@ -12079,7 +12171,7 @@ var EmojiPicker = memo(function EmojiPicker2({
12079
12171
  className: tv.container({ className }),
12080
12172
  style: rootStyle,
12081
12173
  children: [
12082
- /* @__PURE__ */ jsxs("div", { className: tv.header(), children: [
12174
+ (showSearch || showCategories) && /* @__PURE__ */ jsxs("div", { className: tv.header(), children: [
12083
12175
  showSearch && /* @__PURE__ */ jsx(
12084
12176
  SearchInput,
12085
12177
  {
@@ -12174,19 +12266,31 @@ var EmojiPicker = memo(function EmojiPicker2({
12174
12266
  },
12175
12267
  virtualItem.key
12176
12268
  );
12177
- }) : /* @__PURE__ */ jsx(EmojiEmpty, { variant })
12269
+ }) : /* @__PURE__ */ jsx(
12270
+ EmojiEmpty,
12271
+ {
12272
+ variant,
12273
+ i18n: {
12274
+ title: i18n.noEmojisFoundTitle,
12275
+ description: i18n.noEmojisFoundDescription
12276
+ }
12277
+ }
12278
+ )
12178
12279
  }
12179
12280
  )
12180
12281
  }
12181
12282
  )
12182
12283
  }
12183
12284
  ),
12184
- /* @__PURE__ */ jsx(
12285
+ showFooter && /* @__PURE__ */ jsx(
12185
12286
  EmojiFooter,
12186
12287
  {
12187
12288
  hoveredEmoji,
12188
12289
  selectedEmoji: value || null,
12189
- variant
12290
+ variant,
12291
+ i18n: {
12292
+ pickAnEmoji: i18n.footerPickAnEmoji
12293
+ }
12190
12294
  }
12191
12295
  ),
12192
12296
  children
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Range } from "../../../range/dist/index.js";
2
+ import { Range as Range2 } from "../../../range/dist/index.js";
3
3
  import { filterFormProps, BaseAdapter } from "./base-adapter.js";
4
4
  function RangeAdapter({
5
5
  className,
@@ -23,7 +23,7 @@ function RangeAdapter({
23
23
  legendMode: true,
24
24
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
25
25
  /* @__PURE__ */ jsx(
26
- Range,
26
+ Range2,
27
27
  {
28
28
  value,
29
29
  onChange: (inputValue) => onChange(inputValue),
@@ -14,7 +14,7 @@ interface IconButtonProps extends Omit<HTMLProps<HTMLElement>, "size" | "as"> {
14
14
  readOnly?: boolean;
15
15
  size?: "default" | "large" | "reset";
16
16
  tooltip?: TooltipProps;
17
- variant?: "default" | "secondary" | "solid" | "highlight" | "ghost" | "dark" | "reset";
17
+ variant?: "default" | "secondary" | "solid" | "highlight" | "ghost" | "dark" | "submit" | "reset";
18
18
  }
19
19
  declare const IconButton: react.ForwardRefExoticComponent<Omit<IconButtonProps, "ref"> & react.RefAttributes<HTMLElement>>;
20
20
 
@@ -28,6 +28,12 @@ var iconButtonTv = tcv({
28
28
  highlight: {},
29
29
  ghost: {},
30
30
  dark: { button: "text-white" },
31
+ submit: {
32
+ button: [
33
+ "bg-[var(--theme-submit-btn-bg)] text-[var(--theme-submit-btn-text)]",
34
+ "focus-visible:border-transparent"
35
+ ]
36
+ },
31
37
  reset: {}
32
38
  },
33
39
  active: {
@@ -141,6 +147,39 @@ var iconButtonTv = tcv({
141
147
  variant: "dark",
142
148
  disabled: true,
143
149
  class: { button: "text-gray-500" }
150
+ },
151
+ {
152
+ variant: "submit",
153
+ active: false,
154
+ disabled: false,
155
+ class: {
156
+ button: ["focus-visible:shadow-focus", "hover:opacity-70", "active:opacity-70"]
157
+ }
158
+ },
159
+ {
160
+ variant: "submit",
161
+ active: true,
162
+ disabled: false,
163
+ class: {
164
+ button: "opacity-70"
165
+ }
166
+ },
167
+ {
168
+ variant: "submit",
169
+ focused: true,
170
+ class: {
171
+ button: ["shadow-focus", "border-transparent"]
172
+ }
173
+ },
174
+ {
175
+ variant: "submit",
176
+ loading: true,
177
+ class: { button: "opacity-70" }
178
+ },
179
+ {
180
+ variant: "submit",
181
+ disabled: true,
182
+ class: { button: "opacity-50" }
144
183
  }
145
184
  ],
146
185
  defaultVariants: {
@@ -67,7 +67,7 @@ interface ListProps extends Omit<HTMLProps<HTMLDivElement>, "size" | "as"> {
67
67
  selection?: boolean;
68
68
  shouldShowReferenceLine?: boolean;
69
69
  size?: "default" | "large";
70
- variant?: "default" | "primary";
70
+ variant?: "default" | "primary" | "dark" | "reset";
71
71
  }
72
72
  interface ListComponentProps extends React.ForwardRefExoticComponent<ListProps & React.RefAttributes<HTMLDivElement>> {
73
73
  Content: typeof ListContent;
@@ -8,9 +8,10 @@ interface MentionItemProps {
8
8
  }
9
9
  interface MdRenderProps {
10
10
  allowedPrefixes?: string[];
11
+ children?: string;
11
12
  className?: string;
12
13
  components?: Partial<Components>;
13
- content: string;
14
+ content?: string;
14
15
  customColor?: {
15
16
  codeBackground?: string;
16
17
  defaultBackground?: string;
@@ -280,13 +280,7 @@ var createMarkdownComponents = (tv, MentionComponent, mentionItems) => {
280
280
  {
281
281
  className: tv.codeBlock(),
282
282
  lineThreshold: void 0,
283
- children: /* @__PURE__ */ jsx(
284
- CodeBlock2.Code,
285
- {
286
- code: children,
287
- language
288
- }
289
- )
283
+ children: /* @__PURE__ */ jsx(CodeBlock2.Code, { language, children })
290
284
  }
291
285
  );
292
286
  },
@@ -409,7 +403,7 @@ var INITIAL_COMPONENTS = {
409
403
  expandable: false,
410
404
  children: [
411
405
  /* @__PURE__ */ jsx(CodeBlock2.Header, { showLineCount: false }),
412
- /* @__PURE__ */ jsx(CodeBlock2.Content, { code: children })
406
+ /* @__PURE__ */ jsx(CodeBlock2.Content, { children })
413
407
  ]
414
408
  }
415
409
  );
@@ -421,6 +415,7 @@ var MdRender = memo(
421
415
  id,
422
416
  components: customComponents,
423
417
  content,
418
+ children,
424
419
  className,
425
420
  mentionRenderComponent,
426
421
  mentionItems,
@@ -429,9 +424,10 @@ var MdRender = memo(
429
424
  size = "default",
430
425
  variant = "default"
431
426
  } = props;
427
+ const markdownContent = content ?? children ?? "";
432
428
  const generatedId = useId();
433
429
  const blockId = id ?? generatedId;
434
- const blocks = useMdBlocks(content);
430
+ const blocks = useMdBlocks(markdownContent);
435
431
  const tv = useMemo(() => mdRenderTv({ size, variant }), [size, variant]);
436
432
  const tvComponents = useMemo(
437
433
  () => createMarkdownComponents(tv, mentionRenderComponent, mentionItems),
@@ -1,8 +1,11 @@
1
1
  import { Components, Options } from 'react-markdown';
2
+ import { BlockPolicyType } from 'harden-react-markdown';
2
3
  type HardenReactMarkdownProps = Options & {
3
4
  allowedImagePrefixes?: string[];
4
5
  allowedLinkPrefixes?: string[];
5
6
  defaultOrigin?: string;
7
+ linkBlockPolicy?: BlockPolicyType;
8
+ imageBlockPolicy?: BlockPolicyType;
6
9
  };
7
10
  interface MarkdownBlockProps extends Omit<HardenReactMarkdownProps, "children"> {
8
11
  components?: Partial<Components>;
@@ -43,6 +43,8 @@ const MdRender = memo(
43
43
  mentionItems,
44
44
  allowedPrefixes,
45
45
  customColor,
46
+ linkBlockPolicy,
47
+ imageBlockPolicy,
46
48
  size = "default",
47
49
  variant = "default"
48
50
  } = props;
@@ -84,6 +86,8 @@ const MdRender = memo(
84
86
  {
85
87
  content: block,
86
88
  components,
89
+ linkBlockPolicy,
90
+ imageBlockPolicy,
87
91
  allowedLinkPrefixes: allowedPrefixes,
88
92
  allowedImagePrefixes: allowedPrefixes
89
93
  },
@@ -1,3 +1,4 @@
1
+ import { BlockPolicyType } from 'harden-react-markdown';
1
2
  import { Components } from 'react-markdown';
2
3
  interface MentionItemProps {
3
4
  [key: string]: unknown;
@@ -6,6 +7,8 @@ interface MentionItemProps {
6
7
  }
7
8
  export interface MdRenderProps {
8
9
  allowedPrefixes?: string[];
10
+ linkBlockPolicy?: BlockPolicyType;
11
+ imageBlockPolicy?: BlockPolicyType;
9
12
  children?: string;
10
13
  className?: string;
11
14
  components?: Partial<Components>;
@@ -458,6 +458,11 @@ declare const MenuContext: react.Context<MenuContextType | null>;
458
458
  interface MenuContextItemProps extends MenuItemProps {
459
459
  customActive?: boolean;
460
460
  exclusiveIndex?: number;
461
+ /**
462
+ * Whether this item is a link item. When true, a link icon will be displayed on the right.
463
+ * The actual link navigation should be handled by the onClick handler.
464
+ */
465
+ asLink?: boolean;
461
466
  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
462
467
  onKeyDown?: (e: React.KeyboardEvent<HTMLButtonElement>) => void;
463
468
  onMouseUp?: (e: React.MouseEvent<HTMLButtonElement>) => void;
@@ -1,7 +1,7 @@
1
1
  import { Button } from "../../button/dist/index.js";
2
2
  import React__default, { memo, forwardRef, useMemo, useContext, createContext, startTransition, useCallback, useRef, useState, useEffect, Children, isValidElement, Fragment as Fragment$1 } from "react";
3
3
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
4
- import { ChevronDownSmall, Check, ChevronRightSmall, ChevronUpSmall } from "@choiceform/icons-react";
4
+ import { ChevronDownSmall, Check, Launch, ChevronRightSmall, ChevronUpSmall } from "@choiceform/icons-react";
5
5
  import { Kbd } from "../../kbd/dist/index.js";
6
6
  import { flushSync } from "react-dom";
7
7
  import { SearchInput } from "../../search-input/dist/index.js";
@@ -418,9 +418,13 @@ var MenuLabel = memo(function MenuLabel2({
418
418
  });
419
419
  MenuLabel.displayName = "MenuLabel";
420
420
  var SCROLL_ARROW_PADDING = 16;
421
+ var MIN_HEIGHT_FOR_ARROWS = 48;
421
422
  var shouldShowArrow = (scrollRef, dir) => {
422
423
  if (scrollRef.current) {
423
424
  const { scrollTop, scrollHeight, clientHeight } = scrollRef.current;
425
+ if (clientHeight < MIN_HEIGHT_FOR_ARROWS) {
426
+ return false;
427
+ }
424
428
  if (dir === "up") {
425
429
  return scrollTop >= SCROLL_ARROW_PADDING;
426
430
  }
@@ -839,18 +843,25 @@ function useMenuTree(config) {
839
843
  handleOpenChange(false);
840
844
  }
841
845
  });
846
+ const handleParentNavigate = useEventCallback((event) => {
847
+ if (event.nodeId === parentId && event.index !== item.index && isControlledOpen) {
848
+ handleOpenChange(false);
849
+ }
850
+ });
842
851
  const cleanupTreeEvents = useEventCallback(() => {
843
852
  if (tree) {
844
853
  tree.events.off("click", handleTreeClick);
845
854
  tree.events.off("menuopen", handleSubMenuOpen);
855
+ tree.events.off("navigate", handleParentNavigate);
846
856
  }
847
857
  });
848
858
  useEffect(() => {
849
859
  if (!tree) return;
850
860
  tree.events.on("click", handleTreeClick);
851
861
  tree.events.on("menuopen", handleSubMenuOpen);
862
+ tree.events.on("navigate", handleParentNavigate);
852
863
  return cleanupTreeEvents;
853
- }, [tree, nodeId, parentId, handleTreeClick, handleSubMenuOpen, cleanupTreeEvents]);
864
+ }, [tree, nodeId, parentId, handleTreeClick, handleSubMenuOpen, handleParentNavigate, cleanupTreeEvents]);
854
865
  useEffect(() => {
855
866
  if (isControlledOpen && tree) {
856
867
  tree.events.emit("menuopen", { parentId, nodeId });
@@ -904,7 +915,9 @@ var MenuContextItem = memo(
904
915
  size: size2,
905
916
  shortcut,
906
917
  prefixElement,
918
+ suffixElement,
907
919
  variant,
920
+ asLink,
908
921
  onClick,
909
922
  onMouseUp,
910
923
  onTouchStart,
@@ -969,6 +982,16 @@ var MenuContextItem = memo(
969
982
  }),
970
983
  [shortcut == null ? void 0 : shortcut.modifier, shortcut == null ? void 0 : shortcut.keys]
971
984
  );
985
+ const suffixConfig = useMemo(() => {
986
+ if (suffixElement !== void 0) return suffixElement;
987
+ if (prefixElement !== void 0 && menu.selection && !customActive && selected) {
988
+ return /* @__PURE__ */ jsx(Check, {});
989
+ }
990
+ if (asLink) {
991
+ return /* @__PURE__ */ jsx(Launch, { className: "h-3 w-3 text-current" });
992
+ }
993
+ return void 0;
994
+ }, [suffixElement, prefixElement, menu.selection, selected, customActive, asLink]);
972
995
  const combinedRef = useCallback(
973
996
  (node) => {
974
997
  item.ref(node);
@@ -991,6 +1014,7 @@ var MenuContextItem = memo(
991
1014
  disabled,
992
1015
  selected,
993
1016
  prefixElement: prefixConfig,
1017
+ suffixElement: suffixConfig,
994
1018
  shortcut: shortcutConfig,
995
1019
  variant,
996
1020
  size: size2,
@@ -1058,7 +1082,12 @@ var MenuContextSubTrigger = memo(
1058
1082
  throw new Error("MenuContextSubTrigger must be used within a MenuContext component");
1059
1083
  }
1060
1084
  const isActive = useMemo(
1061
- () => item.index === menu.activeIndex || !!active,
1085
+ () => {
1086
+ if (menu.activeIndex !== null && menu.activeIndex !== void 0) {
1087
+ return item.index === menu.activeIndex;
1088
+ }
1089
+ return !!active;
1090
+ },
1062
1091
  [item.index, menu.activeIndex, active]
1063
1092
  );
1064
1093
  const handleFocus = useEventCallback((event) => {