@paubox/ui 3.0.0 → 3.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.
package/index.esm.js CHANGED
@@ -29999,7 +29999,7 @@ function _templateObject2$7() {
29999
29999
  }
30000
30000
  function _templateObject3$6() {
30001
30001
  var data = _tagged_template_literal$8([
30002
- "\n width: 45px;\n text-align: center;\n"
30002
+ "\n width: 45px;\n text-align: center;\n padding-top: 0.3rem;\n padding-bottom: 0.3rem;\n line-height: 1rem;\n"
30003
30003
  ]);
30004
30004
  _templateObject3$6 = function _templateObject() {
30005
30005
  return data;
@@ -31069,11 +31069,20 @@ var formatDate = function(iso) {
31069
31069
  // with non-memoized callbacks from the parent) drove an infinite render
31070
31070
  // loop on pages that don't pass `localCandidates`.
31071
31071
  var EMPTY_CANDIDATES = [];
31072
+ // Default for the optional `decodeHeader` prop — pass-through.
31073
+ var identityDecode = function(s) {
31074
+ return s;
31075
+ };
31072
31076
  // ─── Component ──────────────────────────────────────────────────────────────
31073
31077
  var SearchOmnibox = function(param) {
31074
31078
  var bar = param.bar, _param_placeholder = param.placeholder, placeholder = _param_placeholder === void 0 ? 'Search' : _param_placeholder, _param_pbSearchBaseUrl = param.pbSearchBaseUrl, pbSearchBaseUrl = _param_pbSearchBaseUrl === void 0 ? '' : _param_pbSearchBaseUrl, _param_getAuthToken = param.getAuthToken, getAuthToken = _param_getAuthToken === void 0 ? function() {
31075
31079
  return '';
31076
- } : _param_getAuthToken, _param_fetchSuggestions = param.fetchSuggestions, fetchSuggestions = _param_fetchSuggestions === void 0 ? true : _param_fetchSuggestions, _param_withHistory = param.withHistory, withHistory = _param_withHistory === void 0 ? true : _param_withHistory, onResultClick = param.onResultClick, onCommit = param.onCommit, onLiveChange = param.onLiveChange, _param_localCandidates = param.localCandidates, localCandidates = _param_localCandidates === void 0 ? EMPTY_CANDIDATES : _param_localCandidates, _param_testId = param.testId, testId = _param_testId === void 0 ? 'search-omnibox' : _param_testId, _param_initialQuery = param.initialQuery, initialQuery = _param_initialQuery === void 0 ? '' : _param_initialQuery;
31080
+ } : _param_getAuthToken, _param_fetchSuggestions = param.fetchSuggestions, fetchSuggestions = _param_fetchSuggestions === void 0 ? true : _param_fetchSuggestions, _param_withHistory = param.withHistory, withHistory = _param_withHistory === void 0 ? true : _param_withHistory, onResultClick = param.onResultClick, onCommit = param.onCommit, onLiveChange = param.onLiveChange, _param_localCandidates = param.localCandidates, localCandidates = _param_localCandidates === void 0 ? EMPTY_CANDIDATES : _param_localCandidates, decodeHeader = param.decodeHeader, _param_testId = param.testId, testId = _param_testId === void 0 ? 'search-omnibox' : _param_testId, _param_initialQuery = param.initialQuery, initialQuery = _param_initialQuery === void 0 ? '' : _param_initialQuery;
31081
+ // Local identity fallback for the optional decoder. Wrapping at use time
31082
+ // (instead of defaulting via destructure) lets us keep the prop strictly
31083
+ // optional and skip an extra closure allocation on every render when the
31084
+ // caller doesn't pass one.
31085
+ var decode = decodeHeader !== null && decodeHeader !== void 0 ? decodeHeader : identityDecode;
31077
31086
  var _useState = _sliced_to_array$4(useState(initialQuery), 2), query = _useState[0], setQuery = _useState[1];
31078
31087
  var _useState1 = _sliced_to_array$4(useState(initialQuery), 2), debouncedQuery = _useState1[0], setDebouncedQuery = _useState1[1];
31079
31088
  var _useState2 = _sliced_to_array$4(useState(false), 2), focused = _useState2[0], setFocused = _useState2[1];
@@ -31811,17 +31820,28 @@ var SearchOmnibox = function(param) {
31811
31820
  children: /*#__PURE__*/ jsx(Close, {})
31812
31821
  })
31813
31822
  ]
31814
- }, "recent-".concat(item.key));
31823
+ }, "recent-".concat(idx, "-").concat(item.key));
31815
31824
  }
31816
31825
  if (item.kind === 'result') {
31817
31826
  var result = results.find(function(r) {
31818
31827
  return r.message_id === item.key;
31819
31828
  });
31820
31829
  if (!result) return null;
31830
+ // Decode RFC 2047 encoded-words ("=?UTF-8?Q?..?=") and other
31831
+ // wire-format escapes before rendering. Backend stores the
31832
+ // raw header bytes; presentation is the caller's concern via
31833
+ // the optional `decodeHeader` prop. When the prop is
31834
+ // unset (non-mail bars), `decode` is identity and this is a
31835
+ // no-op. Highlight markup is left as-is — it's a snippet
31836
+ // composed server-side from the indexed (already-tokenized)
31837
+ // text and shouldn't be re-decoded.
31838
+ var decodedSubject = decode(result.subject);
31839
+ var decodedFrom = decode(result.from);
31821
31840
  var _result_to;
31841
+ var decodedTo = ((_result_to = result.to) !== null && _result_to !== void 0 ? _result_to : []).map(decode);
31822
31842
  var participants = [
31823
- result.from
31824
- ].concat(_to_consumable_array$2((_result_to = result.to) !== null && _result_to !== void 0 ? _result_to : [])).filter(Boolean).join(', ');
31843
+ decodedFrom
31844
+ ].concat(_to_consumable_array$2(decodedTo)).filter(Boolean).join(', ');
31825
31845
  return /*#__PURE__*/ jsxs(DropdownRow, {
31826
31846
  id: optionId,
31827
31847
  role: "option",
@@ -31845,7 +31865,7 @@ var SearchOmnibox = function(param) {
31845
31865
  __html: sanitizeHighlight(result.highlight_subject)
31846
31866
  }
31847
31867
  }) : /*#__PURE__*/ jsx("strong", {
31848
- children: result.subject
31868
+ children: decodedSubject
31849
31869
  }),
31850
31870
  /*#__PURE__*/ jsx("span", {
31851
31871
  style: {
@@ -31860,7 +31880,7 @@ var SearchOmnibox = function(param) {
31860
31880
  children: formatDate(result.timestamp)
31861
31881
  })
31862
31882
  ]
31863
- }, "result-".concat(item.key));
31883
+ }, "result-".concat(idx, "-").concat(item.key));
31864
31884
  }
31865
31885
  if (item.kind === 'local') {
31866
31886
  return /*#__PURE__*/ jsx(DropdownRow, {
@@ -31878,7 +31898,7 @@ var SearchOmnibox = function(param) {
31878
31898
  children: /*#__PURE__*/ jsx(RowText, {
31879
31899
  children: item.key
31880
31900
  })
31881
- }, "local-".concat(item.key));
31901
+ }, "local-".concat(idx, "-").concat(item.key));
31882
31902
  }
31883
31903
  // footer
31884
31904
  return /*#__PURE__*/ jsxs(FooterRow, {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@paubox/ui",
3
3
  "author": "Paubox, Inc.",
4
4
  "description": "Paubox Component Library",
5
- "version": "3.0.0",
5
+ "version": "3.0.2",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "publishConfig": {
@@ -85,6 +85,16 @@ export interface SearchOmniboxProps {
85
85
  * Fires in both `local` and `remote` modes. Optional — pages that
86
86
  * only care about explicit commits should just not pass this. */
87
87
  onLiveChange?: (query: string) => void;
88
+ /** Optional decoder applied to header fields (`from`, `to`, `subject`)
89
+ * on suggestion rows before they're rendered. Use this to handle
90
+ * RFC 2047 encoded-words ("=?UTF-8?Q?Re:_=E2=9A=A1?=") or other
91
+ * on-the-wire encodings the backend hasn't already unwrapped.
92
+ *
93
+ * Kept as a prop (rather than hardcoded) so the component stays
94
+ * mail-agnostic; mail-bar callers wire in `decodeMimeHeader` from
95
+ * paubox-next's `utils/mimeHeader`, non-mail bars can leave it
96
+ * undefined. Defaults to identity. */
97
+ decodeHeader?: (value: string) => string;
88
98
  /** Optional candidate strings to filter client-side when
89
99
  * `fetchSuggestions={false}` (e.g. ruleset names, usernames). Ignored
90
100
  * when `fetchSuggestions` is truthy — pb_search drives the suggestions
@@ -95,4 +105,4 @@ export interface SearchOmniboxProps {
95
105
  /** Optional initial query (e.g. when restoring from URL state). */
96
106
  initialQuery?: string;
97
107
  }
98
- export declare const SearchOmnibox: ({ bar, placeholder, pbSearchBaseUrl, getAuthToken, fetchSuggestions, withHistory, onResultClick, onCommit, onLiveChange, localCandidates, testId, initialQuery, }: SearchOmniboxProps) => import("@emotion/react/jsx-runtime").JSX.Element;
108
+ export declare const SearchOmnibox: ({ bar, placeholder, pbSearchBaseUrl, getAuthToken, fetchSuggestions, withHistory, onResultClick, onCommit, onLiveChange, localCandidates, decodeHeader, testId, initialQuery, }: SearchOmniboxProps) => import("@emotion/react/jsx-runtime").JSX.Element;