@rufous/ui 0.3.64 → 0.3.67

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/dist/main.cjs CHANGED
@@ -13563,6 +13563,15 @@ var IconCheck = () => /* @__PURE__ */ React197.createElement("svg", { ...s }, /*
13563
13563
  var IconPaste = () => /* @__PURE__ */ React197.createElement("svg", { ...s }, /* @__PURE__ */ React197.createElement("path", { d: "M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z" }));
13564
13564
 
13565
13565
  // lib/RufousTextEditor/Toolbar.tsx
13566
+ var BASIC_MOBILE_BUTTONS = /* @__PURE__ */ new Set([
13567
+ "undo",
13568
+ "redo",
13569
+ "bold",
13570
+ "italic",
13571
+ "link",
13572
+ "ul",
13573
+ "ol"
13574
+ ]);
13566
13575
  var COLOR_PALETTE = [
13567
13576
  // Row 1: blacks/grays
13568
13577
  "#000000",
@@ -14010,7 +14019,47 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14010
14019
  const [todoEnabled, setTodoEnabled] = (0, import_react53.useState)(false);
14011
14020
  const ttsRef = (0, import_react53.useRef)(null);
14012
14021
  const sttRef = (0, import_react53.useRef)(null);
14013
- const show = (id) => !visibleButtons || visibleButtons.has(id);
14022
+ const [isMobile, setIsMobile] = (0, import_react53.useState)(false);
14023
+ const [expanded, setExpanded] = (0, import_react53.useState)(false);
14024
+ const [overflows, setOverflows] = (0, import_react53.useState)(false);
14025
+ const [winW, setWinW] = (0, import_react53.useState)(typeof window !== "undefined" ? window.innerWidth : 0);
14026
+ const rowRef = (0, import_react53.useRef)(null);
14027
+ (0, import_react53.useEffect)(() => {
14028
+ if (typeof window === "undefined" || !window.matchMedia) return;
14029
+ const mq = window.matchMedia("(max-width: 600px)");
14030
+ const update = () => setIsMobile(mq.matches);
14031
+ update();
14032
+ mq.addEventListener("change", update);
14033
+ return () => mq.removeEventListener("change", update);
14034
+ }, []);
14035
+ (0, import_react53.useEffect)(() => {
14036
+ if (typeof window === "undefined") return;
14037
+ const onResize = () => {
14038
+ setWinW(window.innerWidth);
14039
+ setOverflows(false);
14040
+ };
14041
+ window.addEventListener("resize", onResize);
14042
+ return () => window.removeEventListener("resize", onResize);
14043
+ }, []);
14044
+ const hasCollapsibleButtons = !visibleButtons ? true : [...visibleButtons].some((b) => !BASIC_MOBILE_BUTTONS.has(b));
14045
+ const collapsedActive = isMobile && overflows && hasCollapsibleButtons && !expanded;
14046
+ const show = (id) => {
14047
+ if (visibleButtons && !visibleButtons.has(id)) return false;
14048
+ if (collapsedActive && !BASIC_MOBILE_BUTTONS.has(id)) return false;
14049
+ return true;
14050
+ };
14051
+ (0, import_react53.useLayoutEffect)(() => {
14052
+ if (collapsedActive) return;
14053
+ const row = rowRef.current;
14054
+ if (!row) return;
14055
+ const kids = Array.from(row.children).filter(
14056
+ (el) => el.offsetParent !== null && !el.classList?.contains("rte-toolbar-toggle")
14057
+ );
14058
+ const firstTop = kids.length ? kids[0].offsetTop : 0;
14059
+ const wraps = kids.some((el) => el.offsetTop - firstTop > 2);
14060
+ const next = isMobile && wraps;
14061
+ setOverflows((prev) => prev === next ? prev : next);
14062
+ }, [collapsedActive, isMobile, expanded, winW, visibleButtons]);
14014
14063
  (0, import_react53.useEffect)(() => {
14015
14064
  if (!editor) return;
14016
14065
  const onTransaction = () => setEditorState((n) => n + 1);
@@ -14084,7 +14133,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14084
14133
  setTimeout(() => setTranslateStatus(""), 2e3);
14085
14134
  }, [editor, translateSource, translateTarget, onTranslate]);
14086
14135
  if (!editor) return null;
14087
- return /* @__PURE__ */ import_react53.default.createElement("div", { className: "toolbar" }, /* @__PURE__ */ import_react53.default.createElement("div", { className: `toolbar-row ${onClose ? "with-close" : ""}` }, (show("undo") || show("redo")) && /* @__PURE__ */ import_react53.default.createElement("div", { className: "toolbar-group" }, show("undo") && /* @__PURE__ */ import_react53.default.createElement(Tooltip, { title: "Undo (Ctrl+Z)", placement: "top" }, /* @__PURE__ */ import_react53.default.createElement(
14136
+ return /* @__PURE__ */ import_react53.default.createElement("div", { className: "toolbar" }, /* @__PURE__ */ import_react53.default.createElement("div", { ref: rowRef, className: `toolbar-row ${onClose ? "with-close" : ""}` }, (show("undo") || show("redo")) && /* @__PURE__ */ import_react53.default.createElement("div", { className: "toolbar-group" }, show("undo") && /* @__PURE__ */ import_react53.default.createElement(Tooltip, { title: "Undo (Ctrl+Z)", placement: "top" }, /* @__PURE__ */ import_react53.default.createElement(
14088
14137
  "button",
14089
14138
  {
14090
14139
  className: "toolbar-btn",
@@ -14599,7 +14648,18 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14599
14648
  return true;
14600
14649
  }).run();
14601
14650
  } }, /* @__PURE__ */ import_react53.default.createElement("span", { className: `task-icon task-${status}` }, /* @__PURE__ */ import_react53.default.createElement("img", { src: images[status], alt: status })), " ", labels[status]);
14602
- })))), onClose && /* @__PURE__ */ import_react53.default.createElement("div", { className: "toolbar-row-right" }, /* @__PURE__ */ import_react53.default.createElement(Tooltip, { title: "Close", placement: "top" }, /* @__PURE__ */ import_react53.default.createElement(
14651
+ }))), isMobile && overflows && hasCollapsibleButtons && /* @__PURE__ */ import_react53.default.createElement(
14652
+ "button",
14653
+ {
14654
+ type: "button",
14655
+ className: `toolbar-btn rte-toolbar-toggle ${expanded ? "is-expanded" : ""}`,
14656
+ onClick: () => setExpanded((v) => !v),
14657
+ title: expanded ? "Show fewer options" : "Show more options",
14658
+ "aria-label": expanded ? "Collapse toolbar" : "Expand toolbar",
14659
+ "aria-expanded": expanded
14660
+ },
14661
+ /* @__PURE__ */ import_react53.default.createElement(ChevronDown, { size: 18 })
14662
+ )), onClose && /* @__PURE__ */ import_react53.default.createElement("div", { className: "toolbar-row-right" }, /* @__PURE__ */ import_react53.default.createElement(Tooltip, { title: "Close", placement: "top" }, /* @__PURE__ */ import_react53.default.createElement(
14603
14663
  "button",
14604
14664
  {
14605
14665
  className: "toolbar-btn btn-cross",
package/dist/main.css CHANGED
@@ -8171,6 +8171,25 @@ pre {
8171
8171
  border-right: none;
8172
8172
  margin-right: 0;
8173
8173
  }
8174
+ .rf-rte-wrapper .toolbar-group:empty {
8175
+ display: none;
8176
+ }
8177
+ .rf-rte-wrapper .rte-toolbar-toggle {
8178
+ margin-left: auto;
8179
+ color: #a81c08;
8180
+ }
8181
+ .rf-rte-wrapper .toolbar-row.with-close .rte-toolbar-toggle {
8182
+ margin-right: 9px;
8183
+ }
8184
+ .rf-rte-wrapper .toolbar-row.with-close .rte-toolbar-toggle.is-expanded {
8185
+ margin-right: -24px;
8186
+ }
8187
+ .rf-rte-wrapper .rte-toolbar-toggle svg {
8188
+ transition: transform 0.2s ease;
8189
+ }
8190
+ .rf-rte-wrapper .rte-toolbar-toggle.is-expanded svg {
8191
+ transform: rotate(180deg);
8192
+ }
8174
8193
  .rf-rte-wrapper .toolbar-btn {
8175
8194
  display: inline-flex;
8176
8195
  align-items: center;
package/dist/main.js CHANGED
@@ -11927,7 +11927,7 @@ function createMentionSuggestion(users) {
11927
11927
  }
11928
11928
 
11929
11929
  // lib/RufousTextEditor/Toolbar.tsx
11930
- import React198, { useState as useState34, useRef as useRef30, useEffect as useEffect27, useCallback as useCallback17 } from "react";
11930
+ import React198, { useState as useState34, useRef as useRef30, useEffect as useEffect27, useLayoutEffect as useLayoutEffect4, useCallback as useCallback17 } from "react";
11931
11931
  import { createPortal as createPortal4 } from "react-dom";
11932
11932
 
11933
11933
  // lib/RufousTextEditor/TextToSpeech.tsx
@@ -13357,6 +13357,15 @@ var IconCheck = () => /* @__PURE__ */ React197.createElement("svg", { ...s }, /*
13357
13357
  var IconPaste = () => /* @__PURE__ */ React197.createElement("svg", { ...s }, /* @__PURE__ */ React197.createElement("path", { d: "M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z" }));
13358
13358
 
13359
13359
  // lib/RufousTextEditor/Toolbar.tsx
13360
+ var BASIC_MOBILE_BUTTONS = /* @__PURE__ */ new Set([
13361
+ "undo",
13362
+ "redo",
13363
+ "bold",
13364
+ "italic",
13365
+ "link",
13366
+ "ul",
13367
+ "ol"
13368
+ ]);
13360
13369
  var COLOR_PALETTE = [
13361
13370
  // Row 1: blacks/grays
13362
13371
  "#000000",
@@ -13804,7 +13813,47 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
13804
13813
  const [todoEnabled, setTodoEnabled] = useState34(false);
13805
13814
  const ttsRef = useRef30(null);
13806
13815
  const sttRef = useRef30(null);
13807
- const show = (id) => !visibleButtons || visibleButtons.has(id);
13816
+ const [isMobile, setIsMobile] = useState34(false);
13817
+ const [expanded, setExpanded] = useState34(false);
13818
+ const [overflows, setOverflows] = useState34(false);
13819
+ const [winW, setWinW] = useState34(typeof window !== "undefined" ? window.innerWidth : 0);
13820
+ const rowRef = useRef30(null);
13821
+ useEffect27(() => {
13822
+ if (typeof window === "undefined" || !window.matchMedia) return;
13823
+ const mq = window.matchMedia("(max-width: 600px)");
13824
+ const update = () => setIsMobile(mq.matches);
13825
+ update();
13826
+ mq.addEventListener("change", update);
13827
+ return () => mq.removeEventListener("change", update);
13828
+ }, []);
13829
+ useEffect27(() => {
13830
+ if (typeof window === "undefined") return;
13831
+ const onResize = () => {
13832
+ setWinW(window.innerWidth);
13833
+ setOverflows(false);
13834
+ };
13835
+ window.addEventListener("resize", onResize);
13836
+ return () => window.removeEventListener("resize", onResize);
13837
+ }, []);
13838
+ const hasCollapsibleButtons = !visibleButtons ? true : [...visibleButtons].some((b) => !BASIC_MOBILE_BUTTONS.has(b));
13839
+ const collapsedActive = isMobile && overflows && hasCollapsibleButtons && !expanded;
13840
+ const show = (id) => {
13841
+ if (visibleButtons && !visibleButtons.has(id)) return false;
13842
+ if (collapsedActive && !BASIC_MOBILE_BUTTONS.has(id)) return false;
13843
+ return true;
13844
+ };
13845
+ useLayoutEffect4(() => {
13846
+ if (collapsedActive) return;
13847
+ const row = rowRef.current;
13848
+ if (!row) return;
13849
+ const kids = Array.from(row.children).filter(
13850
+ (el) => el.offsetParent !== null && !el.classList?.contains("rte-toolbar-toggle")
13851
+ );
13852
+ const firstTop = kids.length ? kids[0].offsetTop : 0;
13853
+ const wraps = kids.some((el) => el.offsetTop - firstTop > 2);
13854
+ const next = isMobile && wraps;
13855
+ setOverflows((prev) => prev === next ? prev : next);
13856
+ }, [collapsedActive, isMobile, expanded, winW, visibleButtons]);
13808
13857
  useEffect27(() => {
13809
13858
  if (!editor) return;
13810
13859
  const onTransaction = () => setEditorState((n) => n + 1);
@@ -13878,7 +13927,7 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
13878
13927
  setTimeout(() => setTranslateStatus(""), 2e3);
13879
13928
  }, [editor, translateSource, translateTarget, onTranslate]);
13880
13929
  if (!editor) return null;
13881
- return /* @__PURE__ */ React198.createElement("div", { className: "toolbar" }, /* @__PURE__ */ React198.createElement("div", { className: `toolbar-row ${onClose ? "with-close" : ""}` }, (show("undo") || show("redo")) && /* @__PURE__ */ React198.createElement("div", { className: "toolbar-group" }, show("undo") && /* @__PURE__ */ React198.createElement(Tooltip, { title: "Undo (Ctrl+Z)", placement: "top" }, /* @__PURE__ */ React198.createElement(
13930
+ return /* @__PURE__ */ React198.createElement("div", { className: "toolbar" }, /* @__PURE__ */ React198.createElement("div", { ref: rowRef, className: `toolbar-row ${onClose ? "with-close" : ""}` }, (show("undo") || show("redo")) && /* @__PURE__ */ React198.createElement("div", { className: "toolbar-group" }, show("undo") && /* @__PURE__ */ React198.createElement(Tooltip, { title: "Undo (Ctrl+Z)", placement: "top" }, /* @__PURE__ */ React198.createElement(
13882
13931
  "button",
13883
13932
  {
13884
13933
  className: "toolbar-btn",
@@ -14393,7 +14442,18 @@ var Toolbar = ({ editor, setLink, onAICommand, onTranslate, onSpeechToText, onTe
14393
14442
  return true;
14394
14443
  }).run();
14395
14444
  } }, /* @__PURE__ */ React198.createElement("span", { className: `task-icon task-${status}` }, /* @__PURE__ */ React198.createElement("img", { src: images[status], alt: status })), " ", labels[status]);
14396
- })))), onClose && /* @__PURE__ */ React198.createElement("div", { className: "toolbar-row-right" }, /* @__PURE__ */ React198.createElement(Tooltip, { title: "Close", placement: "top" }, /* @__PURE__ */ React198.createElement(
14445
+ }))), isMobile && overflows && hasCollapsibleButtons && /* @__PURE__ */ React198.createElement(
14446
+ "button",
14447
+ {
14448
+ type: "button",
14449
+ className: `toolbar-btn rte-toolbar-toggle ${expanded ? "is-expanded" : ""}`,
14450
+ onClick: () => setExpanded((v) => !v),
14451
+ title: expanded ? "Show fewer options" : "Show more options",
14452
+ "aria-label": expanded ? "Collapse toolbar" : "Expand toolbar",
14453
+ "aria-expanded": expanded
14454
+ },
14455
+ /* @__PURE__ */ React198.createElement(ChevronDown, { size: 18 })
14456
+ )), onClose && /* @__PURE__ */ React198.createElement("div", { className: "toolbar-row-right" }, /* @__PURE__ */ React198.createElement(Tooltip, { title: "Close", placement: "top" }, /* @__PURE__ */ React198.createElement(
14397
14457
  "button",
14398
14458
  {
14399
14459
  className: "toolbar-btn btn-cross",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rufous/ui",
3
3
  "private": false,
4
- "version": "0.3.64",
4
+ "version": "0.3.67",
5
5
  "type": "module",
6
6
  "description": "Experimental: A lightweight React UI component library (Beta)",
7
7
  "style": "./dist/main.css",