@ioca/react 1.5.4 → 1.5.6

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 (31) hide show
  1. package/lib/cjs/components/editor/controls.js +19 -37
  2. package/lib/cjs/components/editor/controls.js.map +1 -1
  3. package/lib/cjs/components/editor/editor.js +34 -27
  4. package/lib/cjs/components/editor/editor.js.map +1 -1
  5. package/lib/cjs/components/editor/memtion.js +99 -6
  6. package/lib/cjs/components/editor/memtion.js.map +1 -1
  7. package/lib/cjs/components/picker/colors/index.js +6 -5
  8. package/lib/cjs/components/picker/colors/index.js.map +1 -1
  9. package/lib/cjs/components/select/select.js +4 -4
  10. package/lib/cjs/components/select/select.js.map +1 -1
  11. package/lib/cjs/components/tabs/tabs.js +1 -1
  12. package/lib/cjs/components/tabs/tabs.js.map +1 -1
  13. package/lib/css/index.css +1 -1
  14. package/lib/css/index.css.map +1 -1
  15. package/lib/css/reset.css +2 -2
  16. package/lib/es/components/editor/controls.js +20 -38
  17. package/lib/es/components/editor/controls.js.map +1 -1
  18. package/lib/es/components/editor/editor.js +35 -28
  19. package/lib/es/components/editor/editor.js.map +1 -1
  20. package/lib/es/components/editor/memtion.js +99 -7
  21. package/lib/es/components/editor/memtion.js.map +1 -1
  22. package/lib/es/components/picker/colors/index.js +6 -5
  23. package/lib/es/components/picker/colors/index.js.map +1 -1
  24. package/lib/es/components/select/select.js +4 -4
  25. package/lib/es/components/select/select.js.map +1 -1
  26. package/lib/es/components/tabs/tabs.js +1 -1
  27. package/lib/es/components/tabs/tabs.js.map +1 -1
  28. package/lib/index.js +162 -80
  29. package/lib/types/components/editor/type.d.ts +1 -1
  30. package/lib/types/components/picker/type.d.ts +3 -1
  31. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -2,10 +2,10 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import classNames from 'classnames';
3
3
  import { debounce, uid, throttle, title } from 'radash';
4
4
  import { useState, useRef, useCallback, useEffect, useMemo, Children, cloneElement, createElement, isValidElement, Fragment as Fragment$1, useTransition, forwardRef, useLayoutEffect, memo, createContext, useContext, useImperativeHandle } from 'react';
5
- import { SkipPreviousRound, CloseRound, MinusRound, PlusRound, InboxTwotone, ClearAllRound, UndoRound, RedoRound, StrikethroughSRound, FormatUnderlinedRound, FormatItalicRound, FormatBoldRound, PlayArrowRound, PauseRound, StopRound, VolumeDownRound, VolumeOffRound, FullscreenRound, FullscreenExitRound, FeedOutlined, AspectRatioRound, OpenInNewRound, FileDownloadOutlined, RotateRightRound, RotateLeftRound, KeyboardArrowLeftRound, KeyboardArrowRightRound, KeyboardDoubleArrowUpRound, SyncAltRound, VisibilityRound, VisibilityOffRound, MoreHorizRound, SearchRound, CheckRound, UnfoldMoreRound, CalendarMonthTwotone, AccessTimeRound, InfoOutlined, KeyboardArrowDownRound, ListAltRound, DriveFolderUploadOutlined, PlusSharp } from '@ricons/material';
5
+ import { SkipPreviousRound, CloseRound, MinusRound, PlusRound, InboxTwotone, UndoRound, RedoRound, FormatBoldRound, FormatItalicRound, FormatUnderlinedRound, StrikethroughSRound, ClearAllRound, PlayArrowRound, PauseRound, StopRound, VolumeDownRound, VolumeOffRound, FullscreenRound, FullscreenExitRound, FeedOutlined, AspectRatioRound, OpenInNewRound, FileDownloadOutlined, RotateRightRound, RotateLeftRound, KeyboardArrowLeftRound, KeyboardArrowRightRound, KeyboardDoubleArrowUpRound, SyncAltRound, VisibilityRound, VisibilityOffRound, MoreHorizRound, SearchRound, CheckRound, UnfoldMoreRound, CalendarMonthTwotone, AccessTimeRound, InfoOutlined, KeyboardArrowDownRound, ListAltRound, DriveFolderUploadOutlined, PlusSharp } from '@ricons/material';
6
6
  import { createRoot } from 'react-dom/client';
7
7
  import { createPortal } from 'react-dom';
8
- import xss, { escapeAttrValue } from 'xss';
8
+ import xss from 'xss';
9
9
  import { renderToStaticMarkup } from 'react-dom/server';
10
10
  import PubSub from 'pubsub-js';
11
11
  import { findAll } from 'highlight-words-core';
@@ -1849,70 +1849,90 @@ const exec = (a, b, c) => {
1849
1849
  return;
1850
1850
  return document.execCommand(a, b, c);
1851
1851
  };
1852
+ const escapeHtmlAttr$1 = (value) => value
1853
+ .replaceAll("&", "&")
1854
+ .replaceAll('"', """)
1855
+ .replaceAll("<", "&lt;")
1856
+ .replaceAll(">", "&gt;");
1852
1857
  const xssOptions = {
1853
1858
  onIgnoreTagAttr(tag, name, value) {
1854
1859
  if (["class", "contenteditable"].includes(name)) {
1855
- return name + '="' + escapeAttrValue(value) + '"';
1860
+ return name + '="' + escapeHtmlAttr$1(value) + '"';
1856
1861
  }
1857
1862
  if (["data-", "style"].includes(name.substring(0, 5))) {
1858
- return name + '="' + escapeAttrValue(value) + '"';
1863
+ return name + '="' + escapeHtmlAttr$1(value) + '"';
1859
1864
  }
1860
1865
  },
1861
1866
  };
1862
1867
  const handleMouseDown = (e) => {
1863
1868
  e.preventDefault();
1864
1869
  };
1865
- const fnMap = {
1866
- bold: {
1867
- icon: jsx(FormatBoldRound, {}),
1868
- onClick: () => exec("bold"),
1869
- },
1870
- italic: {
1871
- icon: jsx(FormatItalicRound, {}),
1872
- onClick: () => exec("italic"),
1873
- },
1874
- underline: {
1870
+ const defaultControls = [
1871
+ { key: "undo", icon: jsx(UndoRound, {}), onClick: () => exec("undo") },
1872
+ { key: "redo", icon: jsx(RedoRound, {}), onClick: () => exec("redo") },
1873
+ { key: "bold", icon: jsx(FormatBoldRound, {}), onClick: () => exec("bold") },
1874
+ { key: "italic", icon: jsx(FormatItalicRound, {}), onClick: () => exec("italic") },
1875
+ {
1876
+ key: "underline",
1875
1877
  icon: jsx(FormatUnderlinedRound, {}),
1876
1878
  onClick: () => exec("underline"),
1877
1879
  },
1878
- strike: {
1880
+ {
1881
+ key: "strike",
1879
1882
  icon: jsx(StrikethroughSRound, {}),
1880
1883
  onClick: () => exec("strikeThrough"),
1881
1884
  },
1882
- redo: {
1883
- icon: jsx(RedoRound, {}),
1884
- onClick: () => exec("redo"),
1885
- },
1886
- undo: {
1887
- icon: jsx(UndoRound, {}),
1888
- onClick: () => exec("undo"),
1889
- },
1890
- clear: {
1885
+ {
1886
+ key: "clear",
1891
1887
  icon: jsx(ClearAllRound, {}),
1892
1888
  onClick: () => exec("removeFormat"),
1893
1889
  },
1894
- };
1895
- const defaultKeys = [
1896
- "undo",
1897
- "redo",
1898
- "bold",
1899
- "italic",
1900
- "underline",
1901
- "strike",
1902
- "clear",
1903
1890
  ];
1904
- const typedFnMap = fnMap;
1905
1891
  function getControls(options) {
1906
1892
  const { controlBtnProps, addtionControls, getSelection } = options;
1907
- const controls = defaultKeys.map((k) => {
1908
- const { icon, onClick } = typedFnMap[k];
1909
- return (jsx(Button, { ...controlBtnProps, onMouseDown: handleMouseDown, onClick: onClick, children: jsx(Icon, { icon: icon }) }, k));
1910
- });
1893
+ const controls = defaultControls.map(({ key, icon, onClick }) => (jsx(Button, { ...controlBtnProps, onMouseDown: handleMouseDown, onClick: onClick, children: jsx(Icon, { icon: icon }) }, key)));
1911
1894
  const extControls = (addtionControls ?? []).map((item, index) => (jsx(Button, { ...controlBtnProps, onMouseDown: handleMouseDown, onClick: (e) => item.onClick?.(getSelection(), e), children: item.icon }, `addtion-${index}`)));
1912
1895
  return [...controls, ...extControls];
1913
1896
  }
1914
1897
 
1915
1898
  const MEMTION_TAG_CLASS_NAME = "i-memtion-tag";
1899
+ const blockTags = new Set([
1900
+ "ADDRESS",
1901
+ "ARTICLE",
1902
+ "ASIDE",
1903
+ "BLOCKQUOTE",
1904
+ "DIV",
1905
+ "DL",
1906
+ "FIELDSET",
1907
+ "FIGCAPTION",
1908
+ "FIGURE",
1909
+ "FOOTER",
1910
+ "FORM",
1911
+ "H1",
1912
+ "H2",
1913
+ "H3",
1914
+ "H4",
1915
+ "H5",
1916
+ "H6",
1917
+ "HEADER",
1918
+ "LI",
1919
+ "MAIN",
1920
+ "NAV",
1921
+ "OL",
1922
+ "P",
1923
+ "PRE",
1924
+ "SECTION",
1925
+ "TABLE",
1926
+ "TD",
1927
+ "TH",
1928
+ "TR",
1929
+ "UL",
1930
+ ]);
1931
+ const escapeHtmlAttr = (value) => value
1932
+ .replaceAll("&", "&amp;")
1933
+ .replaceAll('"', "&quot;")
1934
+ .replaceAll("<", "&lt;")
1935
+ .replaceAll(">", "&gt;");
1916
1936
  const getInsertNode = (memtion, option) => memtion?.insert?.(option) ?? option.value;
1917
1937
  const getInsertText = (memtion, option) => {
1918
1938
  const nextNode = getInsertNode(memtion, option);
@@ -1927,7 +1947,7 @@ const getInsertHtml = (memtion, option, sanitizeValue) => {
1927
1947
  return "";
1928
1948
  }
1929
1949
  const content = sanitizeValue(renderToStaticMarkup(jsx(Fragment, { children: nextNode })));
1930
- return `<span class="${MEMTION_TAG_CLASS_NAME}" contenteditable="false" data-memtion-value="${escapeAttrValue(String(option.value))}">${content}</span>`;
1950
+ return `<span class="${MEMTION_TAG_CLASS_NAME}" contenteditable="false" data-memtion-value="${escapeHtmlAttr(String(option.value))}">${content}</span>`;
1931
1951
  };
1932
1952
  const getSelectionRect = (range) => {
1933
1953
  if (!range)
@@ -1958,14 +1978,11 @@ const insertMemtionOption = ({ editor, range, mode, memtion, option, sanitizeVal
1958
1978
  const html = getInsertHtml(memtion, option, sanitizeValue);
1959
1979
  const fragment = nextRange.createContextualFragment(html);
1960
1980
  const lastNode = fragment.lastChild;
1961
- const spacing = document.createTextNode(" ");
1962
1981
  nextRange.insertNode(fragment);
1963
1982
  if (lastNode) {
1964
1983
  nextRange.setStartAfter(lastNode);
1965
1984
  nextRange.collapse(true);
1966
1985
  }
1967
- nextRange.insertNode(spacing);
1968
- nextRange.setStartAfter(spacing);
1969
1986
  }
1970
1987
  nextRange.collapse(true);
1971
1988
  browserSelection.removeAllRanges();
@@ -1995,6 +2012,60 @@ const filterMemtionOptions = (options, keyword) => {
1995
2012
  };
1996
2013
  const isMemtionTag = (node) => node instanceof HTMLElement &&
1997
2014
  node.classList.contains(MEMTION_TAG_CLASS_NAME);
2015
+ const appendBreak = (container) => {
2016
+ if (!container.lastChild || container.lastChild.nodeName === "BR") {
2017
+ return;
2018
+ }
2019
+ container.appendChild(document.createElement("br"));
2020
+ };
2021
+ const appendPlaintextOnMemtionNode = (container, node) => {
2022
+ if (!node)
2023
+ return;
2024
+ if (node.nodeType === Node.TEXT_NODE) {
2025
+ container.appendChild(document.createTextNode((node.textContent ?? "").replaceAll("\r", "")));
2026
+ return;
2027
+ }
2028
+ if (!(node instanceof HTMLElement)) {
2029
+ return;
2030
+ }
2031
+ if (isMemtionTag(node)) {
2032
+ const tag = document.createElement("span");
2033
+ const memtionValue = node.getAttribute("data-memtion-value");
2034
+ tag.className = MEMTION_TAG_CLASS_NAME;
2035
+ tag.setAttribute("contenteditable", "false");
2036
+ if (memtionValue !== null) {
2037
+ tag.setAttribute("data-memtion-value", memtionValue);
2038
+ }
2039
+ tag.innerHTML = node.innerHTML;
2040
+ container.appendChild(tag);
2041
+ return;
2042
+ }
2043
+ if (node.tagName === "BR") {
2044
+ appendBreak(container);
2045
+ return;
2046
+ }
2047
+ Array.from(node.childNodes).forEach((child) => {
2048
+ appendPlaintextOnMemtionNode(container, child);
2049
+ });
2050
+ if (blockTags.has(node.tagName)) {
2051
+ appendBreak(container);
2052
+ }
2053
+ };
2054
+ const sanitizePlaintextOnMemtionHtml = (value) => {
2055
+ if (typeof document === "undefined") {
2056
+ return value;
2057
+ }
2058
+ const source = document.createElement("div");
2059
+ const result = document.createElement("div");
2060
+ source.innerHTML = value;
2061
+ Array.from(source.childNodes).forEach((child) => {
2062
+ appendPlaintextOnMemtionNode(result, child);
2063
+ });
2064
+ while (result.lastChild?.nodeName === "BR") {
2065
+ result.lastChild.remove();
2066
+ }
2067
+ return result.innerHTML;
2068
+ };
1998
2069
  const getAdjacentMemtionTag = (range, direction) => {
1999
2070
  const { startContainer, startOffset } = range;
2000
2071
  if (startContainer.nodeType === Node.TEXT_NODE) {
@@ -2052,11 +2123,15 @@ const Memtion = (props) => {
2052
2123
  if (!visible || !rect || !options?.length) {
2053
2124
  return null;
2054
2125
  }
2055
- return (jsx(List$1, { className: "i-editor-memtion", type: "option", style: {
2126
+ const content = (jsx(List$1, { className: "i-editor-memtion", type: "option", style: {
2056
2127
  position: "fixed",
2057
2128
  top: rect.bottom,
2058
2129
  left: rect.left,
2059
2130
  }, children: options.map((option, i) => (jsx(List$1.Item, { type: "option", active: i === activeIndex, onMouseDown: (e) => e.preventDefault(), onMouseEnter: () => onActiveChange?.(i), onClick: () => onSelect?.(option), children: option.label }, `${option.value}-${i}`))) }));
2131
+ if (typeof document === "undefined") {
2132
+ return content;
2133
+ }
2134
+ return createPortal(content, document.body);
2060
2135
  };
2061
2136
  var Memtion$1 = memo(Memtion);
2062
2137
 
@@ -2071,18 +2146,28 @@ const Editor = (props) => {
2071
2146
  const selectionRef = useRef(null);
2072
2147
  const memtionTriggerRangeRef = useRef(null);
2073
2148
  const pendingMemtionRef = useRef(false);
2149
+ const isPlaintextMode = mode === "plaintext";
2150
+ const isRichMode = mode === "rich";
2151
+ const isPlaintextOnMemtionMode = mode === "plaintextOnMemtion";
2074
2152
  const [memtionVisible, setMemtionVisible] = useState(false);
2075
2153
  const [memtionRect, setMemtionRect] = useState(null);
2076
2154
  const [memtionKeyword, setMemtionKeyword] = useState("");
2077
2155
  const [memtionActiveIndex, setMemtionActiveIndex] = useState(0);
2078
2156
  const memtionOptions = useMemo(() => filterMemtionOptions(memtion?.options ?? [], memtionKeyword), [memtion?.options, memtionKeyword]);
2079
2157
  const sanitizeValue = (nextValue) => {
2080
- if (mode === "plaintext") {
2158
+ if (isPlaintextMode) {
2081
2159
  return nextValue === "\n" ? "" : nextValue;
2082
2160
  }
2083
- const safeHtml = xss(nextValue, xssOptions);
2161
+ const safeHtml = isPlaintextOnMemtionMode
2162
+ ? sanitizePlaintextOnMemtionHtml(xss(nextValue, xssOptions))
2163
+ : xss(nextValue, xssOptions);
2084
2164
  return safeHtml === "<br>" ? "" : safeHtml;
2085
2165
  };
2166
+ const syncHeight = () => {
2167
+ if (autosize && editorRef.current) {
2168
+ editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;
2169
+ }
2170
+ };
2086
2171
  const rememberSelection = () => {
2087
2172
  if (!editorRef.current)
2088
2173
  return;
@@ -2102,18 +2187,18 @@ const Editor = (props) => {
2102
2187
  if (!editorRef.current)
2103
2188
  return;
2104
2189
  const safeValue = sanitizeValue(nextValue);
2105
- if (mode === "plaintext") {
2190
+ if (isPlaintextMode) {
2106
2191
  editorRef.current.textContent = safeValue;
2107
2192
  return;
2108
2193
  }
2109
2194
  editorRef.current.innerHTML = safeValue;
2110
2195
  };
2111
2196
  const getEditorValue = (sanitize = false) => {
2112
- if (!editorRef.current)
2113
- return "";
2114
- const nextValue = mode === "plaintext"
2115
- ? (editorRef.current.textContent ?? "")
2116
- : editorRef.current.innerHTML;
2197
+ const nextValue = !editorRef.current
2198
+ ? ""
2199
+ : isPlaintextMode
2200
+ ? (editorRef.current.textContent ?? "")
2201
+ : editorRef.current.innerHTML;
2117
2202
  return sanitize ? sanitizeValue(nextValue) : nextValue;
2118
2203
  };
2119
2204
  const hideMemtion = () => {
@@ -2145,22 +2230,18 @@ const Editor = (props) => {
2145
2230
  if (e.defaultPrevented)
2146
2231
  return;
2147
2232
  e.preventDefault();
2148
- if (mode === "plaintext") {
2149
- const text = e.clipboardData.getData("text/plain");
2150
- exec("insertText", false, text);
2151
- return;
2152
- }
2153
2233
  const html = e.clipboardData.getData("text/html");
2154
- if (html) {
2155
- exec("insertHTML", false, sanitizeValue(html));
2156
- return;
2157
- }
2158
2234
  const text = e.clipboardData.getData("text/plain");
2159
- exec("insertText", false, text);
2235
+ const pasteValue = isPlaintextMode
2236
+ ? text
2237
+ : html
2238
+ ? sanitizeValue(html)
2239
+ : text;
2240
+ exec(isPlaintextMode ? "insertText" : "insertHTML", false, pasteValue);
2160
2241
  };
2161
2242
  const handleKeyDown = (e) => {
2162
2243
  onKeyDown?.(e);
2163
- if (mode === "rich" &&
2244
+ if (!isPlaintextMode &&
2164
2245
  (e.key === "Backspace" || e.key === "Delete") &&
2165
2246
  removeAdjacentMemtionTag(editorRef.current, e.key)) {
2166
2247
  e.preventDefault();
@@ -2197,7 +2278,7 @@ const Editor = (props) => {
2197
2278
  switch (e.key) {
2198
2279
  case "Tab":
2199
2280
  e.preventDefault();
2200
- exec(mode === "plaintext" ? "insertText" : "insertHTML", false, mode === "plaintext" ? "\t" : "&#09;");
2281
+ exec(isRichMode ? "insertHTML" : "insertText", false, isRichMode ? "&#09;" : "\t");
2201
2282
  break;
2202
2283
  case "Enter":
2203
2284
  if (!onEnter)
@@ -2214,9 +2295,7 @@ const Editor = (props) => {
2214
2295
  if (getEditorValue(true) === nextValue)
2215
2296
  return;
2216
2297
  setEditorValue(nextValue);
2217
- if (autosize) {
2218
- editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;
2219
- }
2298
+ syncHeight();
2220
2299
  }, [autosize, mode, value]);
2221
2300
  useEffect(() => {
2222
2301
  if (!memtionOptions.length) {
@@ -2228,6 +2307,11 @@ const Editor = (props) => {
2228
2307
  const handleInput = (e) => {
2229
2308
  const rawValue = getEditorValue();
2230
2309
  let nextValue = sanitizeValue(rawValue);
2310
+ if (isPlaintextOnMemtionMode &&
2311
+ rawValue !== nextValue &&
2312
+ editorRef.current) {
2313
+ setEditorValue(nextValue);
2314
+ }
2231
2315
  if (!nextValue && rawValue && editorRef.current) {
2232
2316
  nextValue = "";
2233
2317
  setEditorValue(nextValue);
@@ -2248,9 +2332,7 @@ const Editor = (props) => {
2248
2332
  setMemtionVisible(true);
2249
2333
  }
2250
2334
  }
2251
- if (autosize && editorRef.current) {
2252
- editorRef.current.style.height = `${editorRef.current.scrollHeight}px`;
2253
- }
2335
+ syncHeight();
2254
2336
  onChange?.(nextValue, e);
2255
2337
  };
2256
2338
  const handleFocus = (e) => {
@@ -2291,7 +2373,7 @@ const Editor = (props) => {
2291
2373
  ...style,
2292
2374
  [autosize ? "minHeight" : "height"]: height,
2293
2375
  width,
2294
- }, children: [!hideControl && (jsx("div", { className: "i-editor-controls", children: controls })), memtion && (jsx(Memtion$1, { visible: memtionVisible, rect: memtionRect, options: memtionOptions, activeIndex: memtionActiveIndex, onActiveChange: setMemtionActiveIndex, onSelect: insertMemtion })), jsx("div", { ref: handleRef, className: "i-editor-content", "data-placeholder": placeholder, contentEditable: mode === "plaintext" ? "plaintext-only" : true, onFocus: handleFocus, onBlur: handleBlur, onMouseUp: handleMouseUp, onPaste: handlePaste, onInput: handleInput, onKeyUp: handleKeyUp, onKeyDown: handleKeyDown, ...restProps })] }));
2376
+ }, children: [!hideControl && (jsx("div", { className: "i-editor-controls", children: controls })), memtion && (jsx(Memtion$1, { visible: memtionVisible, rect: memtionRect, options: memtionOptions, activeIndex: memtionActiveIndex, onActiveChange: setMemtionActiveIndex, onSelect: insertMemtion })), jsx("div", { ref: handleRef, className: "i-editor-content", "data-placeholder": placeholder, contentEditable: isPlaintextMode ? "plaintext-only" : true, onFocus: handleFocus, onBlur: handleBlur, onMouseUp: handleMouseUp, onPaste: handlePaste, onInput: handleInput, onKeyUp: handleKeyUp, onKeyDown: handleKeyDown, ...restProps })] }));
2295
2377
  };
2296
2378
 
2297
2379
  const Flex = (props) => {
@@ -3929,7 +4011,7 @@ const displayValue = (config) => {
3929
4011
  };
3930
4012
 
3931
4013
  const Select = (props) => {
3932
- const { ref, type = "text", name, label, value = "", placeholder, options = [], multiple, prepend, append, labelInline, style, className, message, status = "normal", hideClear, hideArrow, maxDisplay, border, filter, tip, filterPlaceholder = "...", popupProps, onSelect, onChange, ...restProps } = props;
4014
+ const { ref, type = "text", name, label, value = "", placeholder, required, options = [], multiple, prepend, append, labelInline, style, className, message, status = "normal", hideClear, hideArrow, maxDisplay, border, filter, tip, filterPlaceholder = "...", popupProps, onSelect, onChange, ...restProps } = props;
3933
4015
  const [filterValue, setFilterValue] = useState("");
3934
4016
  const [selectedValue, setSelectedValue] = useState(value);
3935
4017
  const [active, setActive] = useState(false);
@@ -3996,11 +4078,11 @@ const Select = (props) => {
3996
4078
  const text = message ?? tip;
3997
4079
  return (jsxs("label", { className: classNames("i-input-label", className, {
3998
4080
  "i-input-inline": labelInline,
3999
- }), style: style, children: [label && jsx("span", { className: 'i-input-label-text', children: label }), jsx(Popup, { position: 'bottom', arrow: false, fitSize: true, offset: 0, ...popupProps, visible: active, trigger: 'none', onVisibleChange: handleVisibleChange, content: jsx(Options, { options: filterOptions, value: selectedValue, multiple: multiple, filter: !!filter, filterPlaceholder: filterPlaceholder, onSelect: handleSelect, onFilter: handleFilterChange }), children: jsxs("div", { className: classNames("i-input-item", {
4081
+ }), style: style, children: [label && (jsxs("span", { className: "i-input-label-text", children: [required && jsx("span", { className: "error", children: "*" }), label] })), jsx(Popup, { position: "bottom", arrow: false, fitSize: true, offset: 0, ...popupProps, visible: active, trigger: "none", onVisibleChange: handleVisibleChange, content: jsx(Options, { options: filterOptions, value: selectedValue, multiple: multiple, filter: !!filter, filterPlaceholder: filterPlaceholder, onSelect: handleSelect, onFilter: handleFilterChange }), children: jsxs("div", { className: classNames("i-input-item", {
4000
4082
  [`i-input-${status}`]: status !== "normal",
4001
4083
  "i-input-borderless": !border,
4002
4084
  "i-input-focus": active,
4003
- }), onClick: () => setActive(true), children: [prepend, jsx("input", { ref: ref, type: 'hidden', value: selectedValue, ...restProps }), multiple ? (hasValue ? (jsx("div", { className: classNames("i-input i-select", {
4085
+ }), onClick: () => setActive(true), children: [prepend, jsx("input", { ref: ref, type: "hidden", value: selectedValue, ...restProps }), multiple ? (hasValue ? (jsx("div", { className: classNames("i-input i-select", {
4004
4086
  "i-select-multiple": multiple,
4005
4087
  }), children: displayValue({
4006
4088
  options: formattedOptions,
@@ -4008,7 +4090,7 @@ const Select = (props) => {
4008
4090
  multiple,
4009
4091
  maxDisplay,
4010
4092
  onSelect: handleSelect,
4011
- }) })) : (jsx("input", { className: 'i-input i-select', placeholder: placeholder, readOnly: true }))) : null, !multiple && (jsx("input", { value: active ? filterValue : displayLabel, className: 'i-input i-select', placeholder: displayLabel || placeholder, onChange: handleInputChange, readOnly: !filter })), jsx(Helpericon, { active: !hideArrow, icon: clearable ? undefined : jsx(UnfoldMoreRound, {}), onClick: handleHelperClick }), append] }) }), text && jsx("span", { className: 'i-input-message', children: text })] }));
4093
+ }) })) : (jsx("input", { className: "i-input i-select", placeholder: placeholder, readOnly: true }))) : null, !multiple && (jsx("input", { value: active ? filterValue : displayLabel, className: "i-input i-select", placeholder: displayLabel || placeholder, onChange: handleInputChange, readOnly: !filter })), jsx(Helpericon, { active: !hideArrow, icon: clearable ? undefined : jsx(UnfoldMoreRound, {}), onClick: handleHelperClick }), append] }) }), text && jsx("span", { className: "i-input-message", children: text })] }));
4012
4094
  };
4013
4095
 
4014
4096
  const ColorMethods = {
@@ -4041,7 +4123,7 @@ const Handle = (props) => {
4041
4123
  };
4042
4124
 
4043
4125
  function ColorPicker(props) {
4044
- const { value, type = "HEX", disabledAlpha, children, usePanel, handle = "both", placeholder = "Colors", popupProps, onChange, } = props;
4126
+ const { value, type = "HEX", disabledAlpha, children, usePanel, handle = "both", placeholder = "Colors", popupProps, onChange, label, required, ...restProps } = props;
4045
4127
  const [colorType, setColorType] = useState(type);
4046
4128
  const [colorValue, setColorValue] = useState(value);
4047
4129
  const [syncValue, setSyncValue] = useState(value);
@@ -4083,11 +4165,11 @@ function ColorPicker(props) {
4083
4165
  }
4084
4166
  }, [popupProps?.visible]);
4085
4167
  if (usePanel) {
4086
- return jsx(ColorsPanel, { ...props });
4168
+ return (jsx(InputContainer, { label: label, required: required, children: jsx(ColorsPanel, { ...restProps, value: value, onChange: onChange }) }));
4087
4169
  }
4088
- return (jsx(Popup, { trigger: 'click', touchable: true, position: 'bottom', ...popupProps, visible: visible, content: jsx(ColorsPanel, { value: syncValue, disabledAlpha: disabledAlpha, panelRender: (panel) => {
4089
- return (jsxs(Fragment, { children: [panel, jsx(Footer, { value: colorValue, type: colorType, onTypeChange: handleTypeChange, onChange: handleValueChange, onOk: handleOk })] }));
4090
- }, onChange: handleChange, onChangeComplete: handleComplete }), onVisibleChange: handleVisibleChange, children: children ?? (jsx(Handle, { color: value, handle: handle, placeholder: placeholder })) }));
4170
+ return (jsx(InputContainer, { label: label, required: required, children: jsx(Popup, { trigger: "click", touchable: true, position: "bottom", ...popupProps, visible: visible, content: jsx(ColorsPanel, { ...restProps, value: syncValue, disabledAlpha: disabledAlpha, panelRender: (panel) => {
4171
+ return (jsxs(Fragment, { children: [panel, jsx(Footer, { value: colorValue, type: colorType, onTypeChange: handleTypeChange, onChange: handleValueChange, onOk: handleOk })] }));
4172
+ }, onChange: handleChange, onChangeComplete: handleComplete }), onVisibleChange: handleVisibleChange, children: children ?? (jsx(Handle, { color: value, handle: handle, placeholder: placeholder })) }) }));
4091
4173
  }
4092
4174
 
4093
4175
  const Dates = (props) => {
@@ -5083,7 +5165,7 @@ const Tabs = ((props) => {
5083
5165
  const { offsetHeight, offsetLeft, offsetTop, offsetWidth } = nav;
5084
5166
  const isLine = type === "line";
5085
5167
  setBarStyle({
5086
- height: !vertical && isLine ? ".25em" : offsetHeight,
5168
+ height: !vertical && isLine ? ".25em" : ".8em",
5087
5169
  width: vertical && isLine ? ".25em" : offsetWidth,
5088
5170
  transform: `translate(${offsetLeft}px, ${offsetTop}px)`,
5089
5171
  });
@@ -20,7 +20,7 @@ interface IEditor extends Omit<HTMLAttributes<HTMLDivElement>, "onInput" | "onCh
20
20
  width?: string | number;
21
21
  height?: string | number;
22
22
  autosize?: boolean;
23
- mode?: "rich" | "plaintext";
23
+ mode?: "rich" | "plaintext" | "plaintextOnMemtion";
24
24
  hideControl?: boolean;
25
25
  addtionControls?: IEditorAddtionControl[];
26
26
  memtion?: IEditorMemtion;
@@ -27,8 +27,10 @@ interface ITimePicker extends BaseInput, IInput {
27
27
  renderItem?: (number: number, active: boolean, unit: "hour" | "minute" | "second") => ReactNode;
28
28
  popupProps?: IPopup;
29
29
  }
30
- interface IColorPicker extends ColorPickerProps {
30
+ interface IColorPicker extends Omit<ColorPickerProps, "value" | "onChange"> {
31
31
  value?: any;
32
+ label?: ReactNode;
33
+ required?: boolean;
32
34
  type?: "HEX" | "RGB" | "HSB";
33
35
  children?: ReactNode;
34
36
  popupProps?: IPopup;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ioca/react",
3
- "version": "1.5.04",
3
+ "version": "1.5.06",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",