@tensor_1/react 2.26.2 → 2.26.3

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.
@@ -21,10 +21,15 @@ function fitsOn(side, a, f, vp, offset, padding) {
21
21
  return spaceOn(side, a, vp, offset) >= need + padding;
22
22
  }
23
23
  function computePosition(anchor, floating, viewport, options = {}) {
24
- const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true } = options;
24
+ const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true, stickySide } = options;
25
25
  const { side: preferred, align } = parsePlacement(placement);
26
26
  let side = preferred;
27
- if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
27
+ const sticky = stickySide === preferred || stickySide === OPPOSITE[preferred] ? stickySide : void 0;
28
+ if (flip && sticky) {
29
+ side = sticky;
30
+ const opp = OPPOSITE[side];
31
+ if (!fitsOn(side, anchor, floating, viewport, offset, padding) && fitsOn(opp, anchor, floating, viewport, offset, padding)) side = opp;
32
+ } else if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
28
33
  const opp = OPPOSITE[side];
29
34
  if (fitsOn(opp, anchor, floating, viewport, offset, padding) || spaceOn(opp, anchor, viewport, offset) > spaceOn(side, anchor, viewport, offset)) {
30
35
  side = opp;
@@ -79,10 +79,15 @@ function fitsOn(side, a, f, vp, offset, padding) {
79
79
  return spaceOn(side, a, vp, offset) >= need + padding;
80
80
  }
81
81
  function computePosition(anchor, floating, viewport, options = {}) {
82
- const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true } = options;
82
+ const { placement = "bottom-start", offset = 6, padding = 8, flip = true, shift = true, stickySide } = options;
83
83
  const { side: preferred, align } = parsePlacement(placement);
84
84
  let side = preferred;
85
- if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
85
+ const sticky = stickySide === preferred || stickySide === OPPOSITE[preferred] ? stickySide : void 0;
86
+ if (flip && sticky) {
87
+ side = sticky;
88
+ const opp = OPPOSITE[side];
89
+ if (!fitsOn(side, anchor, floating, viewport, offset, padding) && fitsOn(opp, anchor, floating, viewport, offset, padding)) side = opp;
90
+ } else if (flip && !fitsOn(side, anchor, floating, viewport, offset, padding)) {
86
91
  const opp = OPPOSITE[side];
87
92
  if (fitsOn(opp, anchor, floating, viewport, offset, padding) || spaceOn(opp, anchor, viewport, offset) > spaceOn(side, anchor, viewport, offset)) {
88
93
  side = opp;
@@ -762,57 +767,206 @@ var import_react4 = require("react");
762
767
  // src/hooks/useAnchoredPosition.ts
763
768
  var import_react3 = require("react");
764
769
  var useIsomorphicLayoutEffect = typeof document !== "undefined" ? import_react3.useLayoutEffect : import_react3.useEffect;
765
- var resolve = (a) => a && typeof a === "object" && "current" in a ? a.current : a ?? null;
770
+ var resolveAnchor = (a) => a && typeof a === "object" && "current" in a ? a.current : a ?? null;
771
+ var anchoringSupported;
772
+ function supportsAnchoring() {
773
+ if (anchoringSupported === void 0) {
774
+ try {
775
+ const css = typeof CSS !== "undefined" ? CSS : void 0;
776
+ anchoringSupported = !!css && typeof css.supports === "function" && css.supports("anchor-name", "--uix-a") && css.supports("position-anchor", "--uix-a") && css.supports("top", "round(anchor(bottom) + 1px, 1px)");
777
+ } catch {
778
+ anchoringSupported = false;
779
+ }
780
+ }
781
+ return anchoringSupported;
782
+ }
783
+ var anchorCount = 0;
784
+ var namesOf = (value) => value.split(",").map((n) => n.trim()).filter((n) => n.startsWith("--"));
785
+ function addAnchorName(el, name) {
786
+ const names = namesOf(getComputedStyle(el).getPropertyValue("anchor-name"));
787
+ if (!names.includes(name)) names.push(name);
788
+ el.style.setProperty("anchor-name", names.join(", "));
789
+ }
790
+ function removeAnchorName(el, name) {
791
+ const names = namesOf(el.style.getPropertyValue("anchor-name")).filter((n) => n !== name);
792
+ if (names.length) el.style.setProperty("anchor-name", names.join(", "));
793
+ else el.style.removeProperty("anchor-name");
794
+ }
795
+ function translationOf(el) {
796
+ const t = getComputedStyle(el).transform;
797
+ if (!t || t === "none" || typeof DOMMatrixReadOnly === "undefined") return { x: 0, y: 0 };
798
+ try {
799
+ const m = new DOMMatrixReadOnly(t);
800
+ return { x: m.m41, y: m.m42 };
801
+ } catch {
802
+ return { x: 0, y: 0 };
803
+ }
804
+ }
805
+ var signed = (n) => `${n < 0 ? "-" : "+"} ${Math.round(Math.abs(n) * 100) / 100}px`;
806
+ var prepared = /* @__PURE__ */ new WeakSet();
766
807
  function useAnchoredPosition(anchor, floatingRef, { open, placement = "bottom-start", offset = 6, padding = 8 }) {
767
808
  const opts = (0, import_react3.useRef)({ placement, offset, padding });
768
809
  opts.current = { placement, offset, padding };
810
+ const session = (0, import_react3.useRef)(false);
811
+ const side = (0, import_react3.useRef)(null);
812
+ const written = (0, import_react3.useRef)("");
813
+ const anchoring = (0, import_react3.useRef)(null);
814
+ const anchoringFailed = (0, import_react3.useRef)(false);
815
+ const anchorName = (0, import_react3.useRef)("");
816
+ const release = (0, import_react3.useCallback)((keepPlace) => {
817
+ const current = anchoring.current;
818
+ if (!current) return;
819
+ anchoring.current = null;
820
+ written.current = "";
821
+ const floating = floatingRef.current;
822
+ if (floating) {
823
+ const s = floating.style;
824
+ if (keepPlace && current.anchor.isConnected) {
825
+ const a = current.anchor.getBoundingClientRect();
826
+ s.top = `${Math.round((current.yEdge === "bottom" ? a.bottom : a.top) + current.dy)}px`;
827
+ s.left = `${Math.round((current.xEdge === "right" ? a.right : a.left) + current.dx)}px`;
828
+ }
829
+ s.removeProperty("position-anchor");
830
+ }
831
+ removeAnchorName(current.anchor, current.name);
832
+ }, [floatingRef]);
769
833
  const reposition = (0, import_react3.useCallback)(() => {
770
- const anchorEl = resolve(anchor);
834
+ const anchorEl = resolveAnchor(anchor);
771
835
  const floating = floatingRef.current;
772
836
  if (!anchorEl || !floating) return;
773
837
  const s = floating.style;
774
- s.position = "fixed";
775
- s.inset = "auto";
776
- s.margin = "0";
838
+ if (!prepared.has(floating)) {
839
+ s.position = "fixed";
840
+ s.inset = "auto";
841
+ s.margin = "0";
842
+ prepared.add(floating);
843
+ written.current = "";
844
+ }
777
845
  const a = anchorEl.getBoundingClientRect();
846
+ const size = { width: floating.offsetWidth, height: floating.offsetHeight };
778
847
  const { placement: p, offset: o, padding: pad } = opts.current;
779
848
  const pos = computePosition(
780
849
  { x: a.x, y: a.y, width: a.width, height: a.height },
781
- { width: floating.offsetWidth, height: floating.offsetHeight },
850
+ size,
782
851
  { width: window.innerWidth, height: window.innerHeight },
783
- { placement: p, offset: o, padding: pad }
852
+ { placement: p, offset: o, padding: pad, stickySide: side.current ?? void 0 }
784
853
  );
785
- s.left = `${Math.round(pos.x)}px`;
786
- s.top = `${Math.round(pos.y)}px`;
787
- floating.dataset.placement = pos.placement;
788
- }, [anchor, floatingRef]);
854
+ const measured = size.width > 0 || size.height > 0;
855
+ if (measured && session.current) side.current = pos.side;
856
+ if (floating.dataset.placement !== pos.placement) floating.dataset.placement = pos.placement;
857
+ const writeFixed = (at) => {
858
+ const left2 = `${Math.round(at.x)}px`;
859
+ const top2 = `${Math.round(at.y)}px`;
860
+ const key2 = `fixed ${left2} ${top2}`;
861
+ if (key2 === written.current) return;
862
+ s.left = left2;
863
+ s.top = top2;
864
+ written.current = key2;
865
+ };
866
+ if (anchoringFailed.current || !supportsAnchoring()) {
867
+ writeFixed(pos);
868
+ return;
869
+ }
870
+ if (anchoring.current && anchoring.current.anchor !== anchorEl) release(false);
871
+ if (!anchoring.current) {
872
+ anchorName.current || (anchorName.current = `--uix-anchor-${++anchorCount}`);
873
+ addAnchorName(anchorEl, anchorName.current);
874
+ s.setProperty("position-anchor", anchorName.current);
875
+ anchoring.current = { anchor: anchorEl, name: anchorName.current, yEdge: "bottom", xEdge: "left", dy: 0, dx: 0, verified: false };
876
+ written.current = "";
877
+ }
878
+ const current = anchoring.current;
879
+ current.yEdge = pos.side === "bottom" ? "bottom" : "top";
880
+ current.xEdge = pos.side === "right" ? "right" : "left";
881
+ current.dy = pos.y - (current.yEdge === "bottom" ? a.bottom : a.top);
882
+ current.dx = pos.x - (current.xEdge === "right" ? a.right : a.left);
883
+ const top = `round(anchor(${current.yEdge}) ${signed(current.dy)}, 1px)`;
884
+ const left = `round(anchor(${current.xEdge}) ${signed(current.dx)}, 1px)`;
885
+ const key = `anchored ${top} ${left}`;
886
+ if (key !== written.current) {
887
+ s.top = top;
888
+ s.left = left;
889
+ written.current = key;
890
+ }
891
+ if (!current.verified && measured) {
892
+ current.verified = true;
893
+ const box = floating.getBoundingClientRect();
894
+ const t = translationOf(floating);
895
+ const dxc = box.left + box.width / 2 - t.x - (pos.x + size.width / 2);
896
+ const dyc = box.top + box.height / 2 - t.y - (pos.y + size.height / 2);
897
+ if (Math.abs(dxc) > 2 || Math.abs(dyc) > 2) {
898
+ anchoringFailed.current = true;
899
+ release(false);
900
+ writeFixed(pos);
901
+ }
902
+ }
903
+ }, [anchor, floatingRef, release]);
789
904
  useIsomorphicLayoutEffect(() => {
790
905
  if (!open) return;
906
+ session.current = true;
791
907
  reposition();
792
- const onScroll = () => reposition();
908
+ const anchorEl = resolveAnchor(anchor);
909
+ const floating = floatingRef.current;
910
+ const onScroll = (event) => {
911
+ const target = event.target;
912
+ if (target && typeof target.contains === "function") {
913
+ if (floating?.contains(target)) return;
914
+ if (anchorEl && !target.contains(anchorEl)) return;
915
+ }
916
+ reposition();
917
+ };
918
+ const onResize = () => reposition();
793
919
  window.addEventListener("scroll", onScroll, { passive: true, capture: true });
794
- window.addEventListener("resize", onScroll);
920
+ window.addEventListener("resize", onResize);
921
+ const observer = typeof ResizeObserver === "function" ? new ResizeObserver(() => reposition()) : null;
922
+ if (floating) observer?.observe(floating);
923
+ if (anchorEl) observer?.observe(anchorEl);
795
924
  return () => {
796
925
  window.removeEventListener("scroll", onScroll, true);
797
- window.removeEventListener("resize", onScroll);
926
+ window.removeEventListener("resize", onResize);
927
+ observer?.disconnect();
928
+ session.current = false;
929
+ side.current = null;
930
+ anchoringFailed.current = false;
931
+ release(true);
798
932
  };
799
- }, [open, reposition]);
933
+ }, [open, reposition, anchor, floatingRef, release]);
934
+ (0, import_react3.useEffect)(() => () => release(false), [release]);
800
935
  return reposition;
801
936
  }
802
937
 
803
938
  // src/components/Popover.tsx
804
939
  var import_jsx_runtime4 = require("react/jsx-runtime");
940
+ var useIsomorphicLayoutEffect2 = typeof document !== "undefined" ? import_react4.useLayoutEffect : import_react4.useEffect;
941
+ var PLACING = "data-uix-placing";
942
+ var isPopoverOpen = (el) => {
943
+ try {
944
+ return el.matches(":popover-open");
945
+ } catch {
946
+ return false;
947
+ }
948
+ };
949
+ var settle = (el) => {
950
+ if (!el.hasAttribute(PLACING)) return;
951
+ getComputedStyle(el).getPropertyValue("transform");
952
+ el.removeAttribute(PLACING);
953
+ };
805
954
  function Popover({
806
955
  popover = "auto",
807
956
  anchor,
808
957
  placement = "bottom-start",
809
958
  offset = 6,
959
+ closeWhenAnchorHidden = false,
960
+ onAnchorHidden,
810
961
  className,
811
962
  children,
812
963
  ...props
813
964
  }) {
814
965
  const ref = (0, import_react4.useRef)(null);
815
966
  const [open, setOpen] = (0, import_react4.useState)(false);
967
+ const openRef = (0, import_react4.useRef)(false);
968
+ const onAnchorHiddenRef = (0, import_react4.useRef)(onAnchorHidden);
969
+ onAnchorHiddenRef.current = onAnchorHidden;
816
970
  const popoverAttr = { popover };
817
971
  const reposition = useAnchoredPosition(anchor ?? null, ref, {
818
972
  open: open && !!anchor,
@@ -822,14 +976,55 @@ function Popover({
822
976
  (0, import_react4.useEffect)(() => {
823
977
  const el = ref.current;
824
978
  if (!el || !anchor) return;
979
+ const hold = (event) => {
980
+ if (event.newState !== "open") return;
981
+ el.setAttribute(PLACING, "");
982
+ window.setTimeout(() => settle(el), 150);
983
+ };
825
984
  const sync = () => {
826
- const isOpen = el.matches(":popover-open");
827
- if (isOpen) reposition();
828
- setOpen(isOpen);
985
+ if (!isPopoverOpen(el)) {
986
+ el.removeAttribute(PLACING);
987
+ setOpen(false);
988
+ return;
989
+ }
990
+ reposition();
991
+ window.setTimeout(() => {
992
+ if (!isPopoverOpen(el)) return;
993
+ if (!openRef.current) {
994
+ setOpen(true);
995
+ return;
996
+ }
997
+ reposition();
998
+ settle(el);
999
+ }, 0);
829
1000
  };
1001
+ el.addEventListener("beforetoggle", hold);
830
1002
  el.addEventListener("toggle", sync);
831
- return () => el.removeEventListener("toggle", sync);
1003
+ return () => {
1004
+ el.removeEventListener("beforetoggle", hold);
1005
+ el.removeEventListener("toggle", sync);
1006
+ el.removeAttribute(PLACING);
1007
+ };
832
1008
  }, [anchor, reposition]);
1009
+ useIsomorphicLayoutEffect2(() => {
1010
+ openRef.current = open;
1011
+ if (open && ref.current) settle(ref.current);
1012
+ }, [open]);
1013
+ (0, import_react4.useEffect)(() => {
1014
+ const el = ref.current;
1015
+ const anchorEl = resolveAnchor(anchor);
1016
+ if (!closeWhenAnchorHidden || !open || !el || !anchorEl || typeof IntersectionObserver !== "function") return;
1017
+ const observer = new IntersectionObserver((entries) => {
1018
+ const latest = entries[entries.length - 1];
1019
+ if (!latest || latest.isIntersecting || !isPopoverOpen(el)) return;
1020
+ onAnchorHiddenRef.current?.();
1021
+ const active = el.ownerDocument.activeElement;
1022
+ if (active && el.contains(active)) active.blur();
1023
+ el.hidePopover();
1024
+ });
1025
+ observer.observe(anchorEl);
1026
+ return () => observer.disconnect();
1027
+ }, [closeWhenAnchorHidden, open, anchor]);
833
1028
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref, className: cx("uix-popover", className), ...popoverAttr, ...props, children });
834
1029
  }
835
1030
 
@@ -846,6 +1041,14 @@ var DEFAULT_EMOJI_PICKER_LABELS = {
846
1041
  loadFailed: "Emoji could not be loaded."
847
1042
  };
848
1043
  var EMOJI_GRID_COLUMNS = 8;
1044
+ var useIsomorphicLayoutEffect3 = typeof document !== "undefined" ? import_react5.useLayoutEffect : import_react5.useEffect;
1045
+ function revealInGrid(grid, cell) {
1046
+ const g = grid.getBoundingClientRect();
1047
+ const c = cell.getBoundingClientRect();
1048
+ const top = g.top + (parseFloat(getComputedStyle(grid).scrollPaddingTop) || 0);
1049
+ if (c.top < top) grid.scrollTop -= top - c.top;
1050
+ else if (c.bottom > g.bottom) grid.scrollTop += c.bottom - g.bottom;
1051
+ }
849
1052
  function EmojiPicker({
850
1053
  onSelect,
851
1054
  trigger,
@@ -867,6 +1070,8 @@ function EmojiPicker({
867
1070
  const searchRef = (0, import_react5.useRef)(null);
868
1071
  const gridRef = (0, import_react5.useRef)(null);
869
1072
  const pointerWasOpen = (0, import_react5.useRef)(null);
1073
+ const closedByAnchor = (0, import_react5.useRef)(false);
1074
+ const pendingJump = (0, import_react5.useRef)(null);
870
1075
  const [open, setOpen] = (0, import_react5.useState)(false);
871
1076
  const [data, setData] = (0, import_react5.useState)(null);
872
1077
  const [failed, setFailed] = (0, import_react5.useState)(false);
@@ -890,10 +1095,14 @@ function EmojiPicker({
890
1095
  setOpen(nowOpen);
891
1096
  onOpenChange?.(nowOpen);
892
1097
  if (nowOpen) {
1098
+ closedByAnchor.current = false;
1099
+ pendingJump.current = null;
893
1100
  setRecent(readRecentEmoji(recentStorageKey));
894
1101
  setQuery("");
895
1102
  setActive(0);
896
- requestAnimationFrame(() => searchRef.current?.focus());
1103
+ requestAnimationFrame(() => searchRef.current?.focus({ preventScroll: true }));
1104
+ } else if (closedByAnchor.current) {
1105
+ closedByAnchor.current = false;
897
1106
  } else if (el.contains(document.activeElement) || document.activeElement === document.body) {
898
1107
  focusTrigger();
899
1108
  }
@@ -925,10 +1134,7 @@ function EmojiPicker({
925
1134
  const el = popoverEl();
926
1135
  if (el && isOpen(el)) el.hidePopover();
927
1136
  };
928
- const sections = (0, import_react5.useMemo)(() => {
929
- if (query.trim()) {
930
- return data ? [{ key: "results", title: labels.search, emojis: searchEmoji(data, query).map((e) => e.emoji) }] : [];
931
- }
1137
+ const browseSections = (0, import_react5.useMemo)(() => {
932
1138
  const list = [];
933
1139
  if (quickPicks?.length) list.push({ key: "quick", title: labels.quickPicks, emojis: [...new Set(quickPicks)] });
934
1140
  if (recent.length) list.push({ key: "recent", title: labels.recent, emojis: recent });
@@ -938,7 +1144,11 @@ function EmojiPicker({
938
1144
  });
939
1145
  }
940
1146
  return list;
941
- }, [query, data, quickPicks, recent, labels.search, labels.quickPicks, labels.recent]);
1147
+ }, [data, quickPicks, recent, labels.quickPicks, labels.recent]);
1148
+ const sections = (0, import_react5.useMemo)(() => {
1149
+ if (!query.trim()) return browseSections;
1150
+ return data ? [{ key: "results", title: labels.search, emojis: searchEmoji(data, query).map((e) => e.emoji) }] : [];
1151
+ }, [query, data, browseSections, labels.search]);
942
1152
  const flat = (0, import_react5.useMemo)(() => sections.flatMap((s) => s.emojis), [sections]);
943
1153
  const sectionStart = (0, import_react5.useMemo)(() => {
944
1154
  const starts = /* @__PURE__ */ new Map();
@@ -955,13 +1165,43 @@ function EmojiPicker({
955
1165
  onSelect(emoji);
956
1166
  hide();
957
1167
  };
958
- const focusCell = (0, import_react5.useCallback)((index) => {
1168
+ const focusCell = (0, import_react5.useCallback)((index, reveal = true) => {
959
1169
  setActive(index);
960
1170
  const find = () => gridRef.current?.querySelector(`[data-emoji-index="${index}"]`);
1171
+ const move = (cell2) => {
1172
+ cell2.focus({ preventScroll: true });
1173
+ if (reveal && gridRef.current) revealInGrid(gridRef.current, cell2);
1174
+ };
961
1175
  const cell = find();
962
- if (cell) cell.focus();
963
- else requestAnimationFrame(() => find()?.focus());
1176
+ if (cell) move(cell);
1177
+ else requestAnimationFrame(() => {
1178
+ const later = find();
1179
+ if (later) move(later);
1180
+ });
964
1181
  }, []);
1182
+ const showSection = (key) => {
1183
+ const grid = gridRef.current;
1184
+ const section = grid?.querySelector(`[data-section="${key}"]`);
1185
+ if (!grid || !section) return;
1186
+ grid.scrollTop += section.getBoundingClientRect().top - grid.getBoundingClientRect().top;
1187
+ const start = sectionStart.get(key);
1188
+ if (start !== void 0) focusCell(start, false);
1189
+ };
1190
+ const onCategory = (key) => {
1191
+ if (!query.trim()) {
1192
+ showSection(key);
1193
+ return;
1194
+ }
1195
+ pendingJump.current = key;
1196
+ setQuery("");
1197
+ setActive(0);
1198
+ };
1199
+ useIsomorphicLayoutEffect3(() => {
1200
+ const key = pendingJump.current;
1201
+ if (key === null || query.trim()) return;
1202
+ pendingJump.current = null;
1203
+ showSection(key);
1204
+ }, [query, sections]);
965
1205
  const onGridKeyDown = (event) => {
966
1206
  const target = event.target;
967
1207
  const index = Number(target.dataset.emojiIndex ?? -1);
@@ -969,7 +1209,7 @@ function EmojiPicker({
969
1209
  const next = emojiGridMove(index, event.key, flat.length, EMOJI_GRID_COLUMNS);
970
1210
  if (event.key === "ArrowUp" && next === null) {
971
1211
  event.preventDefault();
972
- searchRef.current?.focus();
1212
+ searchRef.current?.focus({ preventScroll: true });
973
1213
  return;
974
1214
  }
975
1215
  if (next === null) return;
@@ -1025,6 +1265,10 @@ function EmojiPicker({
1025
1265
  className: "uix-emoji-picker-popover",
1026
1266
  role: "dialog",
1027
1267
  "aria-label": labels.dialog,
1268
+ closeWhenAnchorHidden: true,
1269
+ onAnchorHidden: () => {
1270
+ closedByAnchor.current = true;
1271
+ },
1028
1272
  children: open ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "uix-emoji-picker uix-emoji-picker--full", lang: locale, children: [
1029
1273
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1030
1274
  "input",
@@ -1044,50 +1288,56 @@ function EmojiPicker({
1044
1288
  spellCheck: false
1045
1289
  }
1046
1290
  ),
1047
- data && !query.trim() ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "uix-emoji-picker__nav", role: "group", "aria-label": labels.categories, children: sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1048
- "button",
1291
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1292
+ "div",
1049
1293
  {
1050
- type: "button",
1051
- className: "uix-emoji-picker__nav-btn",
1052
- "aria-label": section.title,
1053
- title: section.title,
1054
- onClick: () => {
1055
- const start = section.emojis.length ? sectionStart.get(section.key) ?? -1 : -1;
1056
- gridRef.current?.querySelector(`[data-section="${section.key}"]`)?.scrollIntoView({ block: "start" });
1057
- if (start >= 0) focusCell(start);
1058
- },
1059
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": "true", children: section.emojis[0] ? renderEmoji(section.emojis[0]) : null })
1060
- },
1061
- section.key
1062
- )) }) : null,
1063
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "uix-emoji-picker__grid", ref: gridRef, onKeyDown: onGridKeyDown, children: sections.map((section) => {
1064
- const start = offset;
1065
- offset += section.emojis.length;
1066
- if (!section.emojis.length) return null;
1067
- const headingId = `${id}-${section.key}`;
1068
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "uix-emoji-picker__section", "data-section": section.key, "aria-labelledby": headingId, children: [
1069
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { id: headingId, className: "uix-emoji-picker__heading", children: section.title }),
1070
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "uix-emoji-picker__cells", role: "group", "aria-labelledby": headingId, children: section.emojis.map((emoji, i) => {
1071
- const index = start + i;
1072
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1073
- "button",
1074
- {
1075
- type: "button",
1076
- className: "uix-emoji-picker__btn",
1077
- "data-emoji-index": index,
1078
- tabIndex: index === activeIndex ? 0 : -1,
1079
- "aria-label": names?.get(emoji) ?? emoji,
1080
- title: names?.get(emoji),
1081
- onClick: () => choose(emoji),
1082
- onFocus: () => setActive(index),
1083
- children: renderEmoji(emoji)
1084
- },
1085
- `${section.key}-${emoji}`
1086
- );
1087
- }) })
1088
- ] }, section.key);
1089
- }) }),
1090
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "uix-emoji-picker__status", role: "status", children: status })
1294
+ className: "uix-emoji-picker__nav",
1295
+ role: data ? "group" : void 0,
1296
+ "aria-label": data ? labels.categories : void 0,
1297
+ children: data ? browseSections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1298
+ "button",
1299
+ {
1300
+ type: "button",
1301
+ className: "uix-emoji-picker__nav-btn",
1302
+ "aria-label": section.title,
1303
+ title: section.title,
1304
+ onClick: () => onCategory(section.key),
1305
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": "true", children: section.emojis[0] ? renderEmoji(section.emojis[0]) : null })
1306
+ },
1307
+ section.key
1308
+ )) : null
1309
+ }
1310
+ ),
1311
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "uix-emoji-picker__grid", ref: gridRef, onKeyDown: onGridKeyDown, children: [
1312
+ sections.map((section) => {
1313
+ const start = offset;
1314
+ offset += section.emojis.length;
1315
+ if (!section.emojis.length) return null;
1316
+ const headingId = `${id}-${section.key}`;
1317
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "uix-emoji-picker__section", "data-section": section.key, "aria-labelledby": headingId, children: [
1318
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { id: headingId, className: "uix-emoji-picker__heading", children: section.title }),
1319
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "uix-emoji-picker__cells", role: "group", "aria-labelledby": headingId, children: section.emojis.map((emoji, i) => {
1320
+ const index = start + i;
1321
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1322
+ "button",
1323
+ {
1324
+ type: "button",
1325
+ className: "uix-emoji-picker__btn",
1326
+ "data-emoji-index": index,
1327
+ tabIndex: index === activeIndex ? 0 : -1,
1328
+ "aria-label": names?.get(emoji) ?? emoji,
1329
+ title: names?.get(emoji),
1330
+ onClick: () => choose(emoji),
1331
+ onFocus: () => setActive(index),
1332
+ children: renderEmoji(emoji)
1333
+ },
1334
+ `${section.key}-${emoji}`
1335
+ );
1336
+ }) })
1337
+ ] }, section.key);
1338
+ }),
1339
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "uix-emoji-picker__status", role: "status", children: status })
1340
+ ] })
1091
1341
  ] }) : null
1092
1342
  }
1093
1343
  )
@@ -1,8 +1,8 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { E as EmojiPickerLabels, a as EmojiLocale } from './emoji-image-WQLh8ZQP.cjs';
4
- export { l as emojiImageFileName } from './emoji-image-WQLh8ZQP.cjs';
5
- import './overlay-position-CEGSz6Z2.cjs';
3
+ import { E as EmojiPickerLabels, a as EmojiLocale } from './emoji-image-6mPZ15Zy.cjs';
4
+ export { l as emojiImageFileName } from './emoji-image-6mPZ15Zy.cjs';
5
+ import './overlay-position-Cjv5E7mn.cjs';
6
6
 
7
7
  type RichTextFeatures = 'full' | 'comment' | 'template';
8
8
  type RichTextHeadingLevel = 1 | 2 | 3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tensor_1/react",
3
- "version": "2.26.2",
3
+ "version": "2.26.3",
4
4
  "description": "Thin React wrappers over the UIx v2 CSS component library.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",