diff --git a/lerna.json b/lerna.json index a8bc05d..a2bb50b 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "packages": [ - "src/packages/*" + "packages/*" ], "version": "independent" } diff --git a/package.json b/package.json index fe051e0..5e244a2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "workspaces": [ - "src/packages/*" + "packages/*" ], "scripts": { "dev": "vite", diff --git a/src/packages/collaboration/package.json b/packages/collaboration/package.json similarity index 100% rename from src/packages/collaboration/package.json rename to packages/collaboration/package.json diff --git a/src/packages/collaboration/src/index.ts b/packages/collaboration/src/index.ts similarity index 100% rename from src/packages/collaboration/src/index.ts rename to packages/collaboration/src/index.ts diff --git a/src/packages/core/package.json b/packages/core/package.json similarity index 100% rename from src/packages/core/package.json rename to packages/core/package.json diff --git a/src/packages/core/src/index.ts b/packages/core/src/index.ts similarity index 100% rename from src/packages/core/src/index.ts rename to packages/core/src/index.ts diff --git a/src/packages/core/src/utils/helper.ts b/packages/core/src/utils/helper.ts similarity index 100% rename from src/packages/core/src/utils/helper.ts rename to packages/core/src/utils/helper.ts diff --git a/src/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts similarity index 100% rename from src/packages/core/src/utils/index.ts rename to packages/core/src/utils/index.ts diff --git a/src/packages/event-manager/package.json b/packages/event-manager/package.json similarity index 100% rename from src/packages/event-manager/package.json rename to packages/event-manager/package.json diff --git a/src/packages/event-manager/src/index.ts b/packages/event-manager/src/index.ts similarity index 100% rename from src/packages/event-manager/src/index.ts rename to packages/event-manager/src/index.ts diff --git a/src/packages/event-manager/src/types.d.ts b/packages/event-manager/src/types.d.ts similarity index 100% rename from src/packages/event-manager/src/types.d.ts rename to packages/event-manager/src/types.d.ts diff --git a/src/packages/formatter/package.json b/packages/formatter/package.json similarity index 100% rename from src/packages/formatter/package.json rename to packages/formatter/package.json diff --git a/src/packages/formatter/src/index.ts b/packages/formatter/src/index.ts similarity index 100% rename from src/packages/formatter/src/index.ts rename to packages/formatter/src/index.ts diff --git a/src/packages/formatter/tsconfig.json b/packages/formatter/tsconfig.json similarity index 100% rename from src/packages/formatter/tsconfig.json rename to packages/formatter/tsconfig.json diff --git a/src/packages/history/package.json b/packages/history/package.json similarity index 100% rename from src/packages/history/package.json rename to packages/history/package.json diff --git a/src/packages/history/src/index.ts b/packages/history/src/index.ts similarity index 100% rename from src/packages/history/src/index.ts rename to packages/history/src/index.ts diff --git a/src/packages/persistence/package.json b/packages/persistence/package.json similarity index 100% rename from src/packages/persistence/package.json rename to packages/persistence/package.json diff --git a/src/packages/persistence/src/index.ts b/packages/persistence/src/index.ts similarity index 100% rename from src/packages/persistence/src/index.ts rename to packages/persistence/src/index.ts diff --git a/src/packages/plugin-manager/package.json b/packages/plugin-manager/package.json similarity index 100% rename from src/packages/plugin-manager/package.json rename to packages/plugin-manager/package.json diff --git a/src/packages/plugin-manager/src/index.ts b/packages/plugin-manager/src/index.ts similarity index 100% rename from src/packages/plugin-manager/src/index.ts rename to packages/plugin-manager/src/index.ts diff --git a/src/packages/selection-manager/package.json b/packages/selection-manager/package.json similarity index 100% rename from src/packages/selection-manager/package.json rename to packages/selection-manager/package.json diff --git a/src/packages/selection-manager/src/index.ts b/packages/selection-manager/src/index.ts similarity index 100% rename from src/packages/selection-manager/src/index.ts rename to packages/selection-manager/src/index.ts diff --git a/src/packages/selection-manager/src/types.d.ts b/packages/selection-manager/src/types.d.ts similarity index 100% rename from src/packages/selection-manager/src/types.d.ts rename to packages/selection-manager/src/types.d.ts diff --git a/src/packages/selection-manager/src/util.ts b/packages/selection-manager/src/util.ts similarity index 100% rename from src/packages/selection-manager/src/util.ts rename to packages/selection-manager/src/util.ts diff --git a/src/packages/selection-manager/tsconfig.json b/packages/selection-manager/tsconfig.json similarity index 100% rename from src/packages/selection-manager/tsconfig.json rename to packages/selection-manager/tsconfig.json diff --git a/src/packages/syntax-highlighter/package.json b/packages/syntax-highlighter/package.json similarity index 100% rename from src/packages/syntax-highlighter/package.json rename to packages/syntax-highlighter/package.json diff --git a/src/packages/syntax-highlighter/src/index.ts b/packages/syntax-highlighter/src/index.ts similarity index 100% rename from src/packages/syntax-highlighter/src/index.ts rename to packages/syntax-highlighter/src/index.ts diff --git a/src/packages/toolbar/package.json b/packages/toolbar/package.json similarity index 100% rename from src/packages/toolbar/package.json rename to packages/toolbar/package.json diff --git a/src/packages/toolbar/src/index.ts b/packages/toolbar/src/index.ts similarity index 100% rename from src/packages/toolbar/src/index.ts rename to packages/toolbar/src/index.ts diff --git a/src/packages/ui/package.json b/packages/ui/package.json similarity index 100% rename from src/packages/ui/package.json rename to packages/ui/package.json diff --git a/packages/ui/src/ColorSelectorRadio.tsx b/packages/ui/src/ColorSelectorRadio.tsx new file mode 100644 index 0000000..1964828 --- /dev/null +++ b/packages/ui/src/ColorSelectorRadio.tsx @@ -0,0 +1,64 @@ +import { ArPopoverSlots } from "@armco/types" + +const textColors: Array = [ + "#172B4D", + "#0747A6", + "#008DA6", + "#006644", + "#FF991F", + "#BF2600", + "#403294", + "#97A0AF", + "#4C9AFF", + "#00B8D9", + "#36B37E", + "#FFC400", + "#FF5630", + "#6554C0", + "#FFFFFF", + "#B3D4FF", + "#B3F5FF", + "#ABF5D1", + "#FFF0B3", + "#FFBDAD", + "#EAE6FF", +] +const bgColors: Array = [ + "#FFFFFF", + "#DCDFE4", + "#C6EDFB", + "#D3F1A7", + "#FEDEC8", + "#FDD0EC", + "#DFD8FD", +] + +const ColorSelectorRadio = ({ + slot, + variant, +}: { + variant: "text" | "background" + slot: ArPopoverSlots +}) => { + const colors = variant === "text" ? textColors : bgColors + return ( +
+ {colors.map((color) => ( + + + + ))} +
+ ) +} + +export default ColorSelectorRadio diff --git a/packages/ui/src/FlexContent.tsx b/packages/ui/src/FlexContent.tsx new file mode 100644 index 0000000..4dc896d --- /dev/null +++ b/packages/ui/src/FlexContent.tsx @@ -0,0 +1,385 @@ +/** + * Document component, that wraps and manages Text components + * - on enter add a new Text component + * + */ +import { + FormEvent, + memo, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react" +import { v4 as uuid } from "uuid" +import { + ArPopoverPositions, + ArPopoverSlots, + ChunkInfo, + CompInfo, + FlexContentProps, + FlexContentType, + LibRepoType, + SelectionInfo, + TextInfo, + TextProps, +} from "@armco/types" +import { + applyTool, // Formatting + DomHelper, + PopoverV2, + selectionHandler, // Selection + splitChunkAtCursor, // Formatting + TextFormatter, +} from "../.." +import * as atoms from "../../atoms" +import * as molecules from "../../molecules" +import "./index.scss" + +const demoDummyState: { + entireSelectionFormatted?: boolean + contentRegistry: FlexContentType +} = { + contentRegistry: {}, +} + +Array.from({ length: 4 }, (i: number) => { + const id = uuid() + demoDummyState.contentRegistry[id] = { + id, + name: "Text", + text: `lorem ipsum${i}`, + order: i, + chunks: {}, + length: -1, + } + return null +}) + +const MemoWrapper = memo( + (props: { componentName: string; props: TextProps; repo: LibRepoType }) => { + const { componentName, props: componentProps, repo } = props + const Component = repo[componentName] + return Component ? ( + + ) : null + }, + (prevProps, props) => { + return ( + JSON.stringify(prevProps.props.descriptor.chunks) !== + JSON.stringify(props.props.descriptor.chunks) + ) + }, +) + +const initId = uuid() +const initText = { + [initId]: { + id: initId, + name: "Text", + text: "", + order: 0, + chunks: {}, + length: -1, + }, +} +const DEFAULT_PREVENTERS = ["Enter", "Backspace", "Delete"] +const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0 +const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) +const isAndroid = /Android/.test(navigator.userAgent) + +const FlexContent = (props: FlexContentProps): JSX.Element => { + const { + allowFormatting, + isEditable = true, + hasFloatingFormatter, + content = initText, + demo, + onCommit, + theme, + } = props + const [contentState, updateContentState] = useState<{ + entireSelectionFormatted?: boolean + contentRegistry: FlexContentType + }>() + const [formatterDisplayed, displayFormatter] = useState(false) + const activeChunkRef = useRef() + const flexContentRef = useRef(null) + const selectionInfoRef = useRef() + const keyRef = useRef() + const repo: LibRepoType = useMemo(() => ({ ...atoms, ...molecules }), []) + const winObj = useMemo(() => DomHelper.getWindowElement(demo), [demo]) + const docObj = useMemo(() => DomHelper.getDocumentElement(demo), [demo]) + const memoizedSelectionHandler = useCallback( + () => + selectionHandler( + activeChunkRef, + docObj, + winObj, + selectionInfoRef, + contentState, + ), + [contentState, docObj, winObj], + ) + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if ((event.ctrlKey || event.metaKey) && event.key === "b") { + event.preventDefault() + selectionInfoRef.current && + contentState && + applyTool( + "bold", + true, + selectionInfoRef.current, + contentState, + (state) => { + updateContentState(state) + selectionInfoRef.current = null + }, + ) + // undoSlots() + } + } + + docObj?.addEventListener("keydown", handleKeyDown) + + return () => { + docObj?.removeEventListener("keydown", handleKeyDown) + } + }, [contentState, docObj]) + + useEffect(() => { + const useContent = content + ? { contentRegistry: content } + : demo + ? demoDummyState + : { contentRegistry: content || {} } + useContent?.contentRegistry && + Object.values(useContent.contentRegistry).forEach( + (obj: TextInfo | CompInfo) => { + obj.length = (obj.text as string)?.length + if (Object.keys(obj.chunks).length === 0) { + const id = uuid() + const end = obj.text ? (obj.text as string).length - 1 : 0 + obj.chunks[id] = { + id, + start: 0, + end, + text: obj.text.substring(0, end), + formats: {}, + parent: obj.id, + } + } + }, + ) + updateContentState(useContent) + }, [content, demo]) + + useEffect(() => { + const flexContentDom = flexContentRef.current + const displayFormatterHandler = () => + winObj?.getSelection()?.toString().length && displayFormatter(true) + // flexContentDom?.addEventListener("focus", memoizedSelectionHandler) + docObj?.addEventListener("selectionchange", memoizedSelectionHandler) + flexContentDom?.addEventListener("mouseup", displayFormatterHandler) + return () => { + // flexContentDom?.removeEventListener("focus", memoizedSelectionHandler) + docObj?.removeEventListener("selectionchange", memoizedSelectionHandler) + flexContentDom?.removeEventListener("mouseup", displayFormatterHandler) + } + }, [winObj, docObj, memoizedSelectionHandler, flexContentRef]) + + useEffect(() => { + if (flexContentRef.current) { + setTimeout(() => flexContentRef.current?.focus(), 10) + } + }, [flexContentRef]) + + const textConfigs = + contentState && + Object.entries(contentState.contentRegistry as FlexContentType) + textConfigs?.sort((t1, t2) => t1[1].order - t2[1].order) + + const handleInput = (e: FormEvent) => { + e.preventDefault() + const input = (e as unknown as InputEvent).data + const selection = winObj?.getSelection() + if (selection) { + const range = selection.getRangeAt(0) + const anchorText = + (selection.anchorNode as HTMLElement).textContent + (input || "") + const cursorPosition = selection.anchorOffset + const startContainer = range.startContainer + if (flexContentRef.current) { + const childNodes = Array.from(flexContentRef.current.childNodes) + childNodes.forEach((node) => { + node.nodeType === Node.TEXT_NODE && node.remove() + }) + } + + if (contentState && activeChunkRef.current) { + const content = contentState.contentRegistry + const textConfig = content[activeChunkRef.current.parent] + textConfig.text = input // TODO: Fix this value, might only capture chunk's text + textConfig.cursorPosition = cursorPosition + if ( + startContainer?.parentNode && + !(startContainer.parentNode as HTMLElement).classList.contains( + "ar-FlexContent", + ) + ) { + textConfig.startContainer = startContainer + } + const activeText = + contentState.contentRegistry[activeChunkRef.current.parent] + const activeChunk = activeText?.chunks[activeChunkRef.current.id] + activeChunk.text = anchorText + activeChunk.end = activeChunk.start + activeChunk.text.length + updateContentState({ ...contentState }) + } + onCommit && onCommit() + keyRef.current = undefined + } + } + + const contentRenders = ( +
{ + const selection = winObj?.getSelection() + if (selection && contentState) { + const range = selection.getRangeAt(0) + if (e.key === "Enter") { + e.preventDefault() + splitChunkAtCursor( + selection, + contentState, + activeChunkRef, + updateContentState, + ) + } else if (e.key === "Backspace") { + if (range && range.startOffset > 0) { + range.setStart(range.startContainer, range.startOffset - 1) + range.deleteContents() + } + } else if (e.key === "Delete") { + if (isMac || isIOS || isAndroid) { + if (range.startOffset > 0) { + range.setStart(range.startContainer, range.startOffset - 1) + range.deleteContents() + } + } else { + // On Windows, "Delete" key deletes character after the cursor + if ( + range.startContainer.textContent && + range.startOffset < range.startContainer.textContent.length + ) { + range.setEnd(range.startContainer, range.startOffset + 1) + range.deleteContents() + } + } + } + } + }} + onBeforeInput={handleInput} + contentEditable={isEditable} + suppressContentEditableWarning={true} + > + {textConfigs?.map((entry) => { + const props: TextProps = { + descriptor: entry[1] as TextInfo, + allowFormatting, + isEditable, + demo, + } + return ( + + ) + })} +
+ ) + + return ( + <> + {isEditable && allowFormatting && hasFloatingFormatter ? ( + displayFormatter(false)} + position={ArPopoverPositions.TOP} + demo={demo} + topOffset={16} + popAtPointer + hideMarker + > + {contentRenders} + { + updateContentState(state) + selectionInfoRef.current = null + }} + selectionInfo={selectionInfoRef.current} + theme={theme} + isFloating + /> + + ) : ( + contentRenders + )} +
+
+
+
Content Registry
+
+            {JSON.stringify(
+              contentState?.contentRegistry,
+              (key, value) => {
+                if (key.startsWith("__reactFiber")) {
+                  if (value.stateNode?.data) {
+                    return value.stateNode.data
+                  } else {
+                    return value.toString()
+                  }
+                }
+                if (key === "id" || key === "length") {
+                  return undefined
+                }
+                return value
+              },
+              2,
+            )}
+          
+
+
+
Active Chunk (ref - no live update)
+
+            {JSON.stringify(activeChunkRef.current, null, 2)}
+          
+
+
+
Selection Info (ref - no live update)
+
+            {JSON.stringify(selectionInfoRef.current, null, 2)}
+          
+
+
+ + ) +} + +export default FlexContent diff --git a/packages/ui/src/TextFormatter.component.scss b/packages/ui/src/TextFormatter.component.scss new file mode 100755 index 0000000..724d1b6 --- /dev/null +++ b/packages/ui/src/TextFormatter.component.scss @@ -0,0 +1,39 @@ +.ar-TextFormatter { + max-height: 2.5rem; + --color-tool-indicator-color: linear-gradient(to right, rgb(101, 84, 192) 25%, rgb(0, 184, 217) 25%, rgb(0, 184, 217) 50%, rgb(255, 153, 31) 50%, rgb(255, 153, 31) 75%, rgb(222, 53, 11) 75%); + --color-tool-indicator-color-inactive: linear-gradient(to right, rgb(151, 160, 175) 25%, rgb(179, 186, 197) 25%, rgb(179, 186, 197) 50%, rgb(223, 225, 230) 50%, rgb(223, 225, 230) 75%, rgb(179, 186, 197) 75%); + .ar-TextTool { + .ar-TextTool__anchor { + height: 2rem; + min-width: 2rem; + transition: background-color 0.3s; + .ar-LoadableIcon { + margin-bottom: 1px; + } + &.active:not(.enabled):hover { + background-color: var(--ar-color-disabled-4-invert) !important; + } + &.enabled { + background-color: #e9f2ff !important; + } + &.for-color .ar-TextTool__color-tool-indicator { + background: var(--color-tool-indicator-color-inactive); + width: 1rem; + height: 3px; + border-radius: 3px; + } + &.for-color.active .ar-TextTool__color-tool-indicator { + background: var(--color-tool-indicator-color); + } + } + } + +} + +.ar-ColorSelectorRadio__button { + outline: 1px solid transparent; + + &:hover { + outline: 1px solid #aeaeae; + } +} diff --git a/packages/ui/src/TextFormatter.tsx b/packages/ui/src/TextFormatter.tsx new file mode 100755 index 0000000..d11a3be --- /dev/null +++ b/packages/ui/src/TextFormatter.tsx @@ -0,0 +1,282 @@ +import { + ArThemes, + TextFormatterTool, + TextFormatterProps, + TextFormat, +} from "@armco/types" +import { TextTool } from "../.." +import "./TextFormatter.component.scss" + +const editToolGroups: { + [key: string]: { + scope: 0 | 1 | 2 + popoverContentClasses?: string + tools: Array + } +} = { + fontStyle: { + scope: 0, + popoverContentClasses: "py-2 px-0", + tools: [ + { + name: "bold", + label: "Bold", + darkModeHoverColor: "#dadada", + value: true, + icon: "fa.FaBold", + tooltip: "Bold", + size: "0.9rem", + }, + { + name: "italic", + label: "Italic", + darkModeHoverColor: "#dadada", + value: true, + icon: "fa.FaItalic", + tooltip: "Oblique", + size: "0.9rem", + }, + { + name: "underline", + label: "Underline", + darkModeHoverColor: "#dadada", + value: true, + icon: "fa.FaUnderline", + tooltip: "Underline", + size: "0.9rem", + }, + { + name: "strikethrough", + label: "Strikethrough", + value: true, + icon: "fa.FaStrikethrough", + tooltip: "Strikethrough", + size: "0.9rem", + }, + { + name: "code", + label: "Code", + value: true, + icon: "fa.FaCode", + tooltip: "Code", + }, + { + name: "scriptPlacement", + label: "Subscript", + value: "sub", + icon: "fa.FaSubscript", + tooltip: "Subscript", + }, + { + name: "scriptPlacement", + label: "SuperScript", + value: "sup", + icon: "fa.FaSuperscript", + tooltip: "Superscript", + }, + ], + }, + size: { + scope: 0, + tools: [ + { + name: "increase-size", + icon: "ri.RiCharacterRecognitionFill", + darkModeHoverColor: "#dadada", + subIcon: "fa.FaLongArrowAltUp", + size: "1.4rem", + tooltip: "Bigger", + }, + { + name: "decrease-size", + icon: "ri.RiCharacterRecognitionFill", + darkModeHoverColor: "#dadada", + subIcon: "fa.FaLongArrowAltDown", + size: "0.9rem", + tooltip: "Smaller", + }, + ], + }, + color: { + scope: 0, + tools: [ + { + name: "foreground", + icon: "ri.RiCharacterRecognitionFill", + darkModeHoverColor: "#dadada", + subIcon: "md.MdKeyboardArrowDown", + subIconSize: "1rem", + tooltip: "Change Text Color", + popover: "textColor", + }, + { + name: "background", + icon: "md.MdEdit", + darkModeHoverColor: "#dadada", + subIcon: "md.MdKeyboardArrowDown", + subIconSize: "1rem", + tooltip: "Change Background Color", + popover: "backgroundColor", + }, + ], + }, + indentation: { + scope: 1, + popoverContentClasses: "py-2 px-0", + tools: [ + { + name: "left-align", + label: "Align Left", + icon: "fa.FaAlignLeft", + darkModeHoverColor: "#dadada", + tooltip: "Align Left", + }, + { + name: "center-align", + label: "Align Center", + icon: "fa.FaAlignCenter", + darkModeHoverColor: "#dadada", + tooltip: "Centre Text", + }, + { + name: "right-align", + label: "Align Right", + icon: "fa.FaAlignRight", + darkModeHoverColor: "#dadada", + tooltip: "Align Right", + }, + { + name: "increase-indent", + label: "Increase Indent", + icon: "im.ImIndentIncrease", + tooltip: "Indent Right", + }, + { + name: "decrease-indent", + label: "Decrease Indent", + icon: "im.ImIndentDecrease", + tooltip: "Indent Right", + }, + ], + }, + clear: { + scope: 0, + tools: [ + { + name: "clear", + icon: "md.MdFormatClear", + darkModeHoverColor: "#dadada", + tooltip: "Clear Formatting", + }, + ], + }, +} + +const TextFormatter = (props: TextFormatterProps): JSX.Element => { + const { + activeFormats, + content, + callback, + demo, + isFloating, + selectionInfo, + theme, + variant = 0, + } = props + + const otherTheme = theme === ArThemes.DARK1 ? ArThemes.LIGHT1 : ArThemes.DARK1 + + const toolRenders = ( + editTools: { + scope: number + popoverContentClasses?: string + tools: Array + }, + category: string, + ) => { + const inScopeTools = editTools.tools + .filter((tool) => !tool.scope || tool.scope <= variant) + .map((t) => { + t.onClick = () => + content && + selectionInfo && + applyTool( + t.name as keyof TextFormat, + t.value, + selectionInfo, + content, + callback, + ) + return t + }) + let initialTools + if (inScopeTools.length > 3) { + initialTools = inScopeTools.slice(0, 2) + initialTools.push({ + name: "more", + icon: "md.MdMoreHoriz", + darkModeHoverColor: "#dadada", + tooltip: "View more", + popover: "moreTools", + popoverContentClasses: editTools.popoverContentClasses, + }) + } else { + initialTools = inScopeTools + } + + const initialRenders = initialTools.map((tool) => ( + + selectionInfo && + content && + tool.name !== "more" && + applyTool( + tool.name as keyof TextFormat, + tool.value, + selectionInfo, + content, + callback, + ) + } + restTools={inScopeTools.length > 3 ? inScopeTools.slice(2) : []} + tool={tool} + theme={(isFloating ? theme : otherTheme) || ArThemes.LIGHT1} + enabled={ + !!(activeFormats && activeFormats[tool.name as keyof TextFormat]) + } + /> + )) + return initialRenders + } + + return ( +
+ {Object.entries(editToolGroups) + .filter((entry) => entry[1].scope <= variant) + .map(([category, editTools], index, arr) => { + return ( +
+ {toolRenders(editTools, category)} +
+ ) + }) + .filter((g) => g)} +
+ ) +} + +export default TextFormatter diff --git a/packages/ui/src/TextTool.tsx b/packages/ui/src/TextTool.tsx new file mode 100644 index 0000000..1c6ef30 --- /dev/null +++ b/packages/ui/src/TextTool.tsx @@ -0,0 +1,131 @@ +import { useState } from "react" +import { + ArPopoverSlots, + ArThemes, + ListItemContent, + TextToolProps, +} from "@armco/types" +import { + ColorSelectorRadio, + List, + LoadableIcon, + PopoverV2, + Tooltip, +} from "../.." + +const popovers = (restTools?: Array, theme?: ArThemes) => ({ + textColor: ( + + ), + backgroundColor: ( + + ), + moreTools: ( + + ), +}) + +const TextTool = ({ + active, + bgClass, + category, + demo, + enabled, + formatter, + restTools, + tool, + theme, +}: TextToolProps) => { + const { + color, + darkModeColor, + name, + icon, + subIcon, + tooltip, + size, + subIconSize, + paddingClass, + popover, + popoverContentClasses, + } = tool + const [hovered, setHovered] = useState() + + const iconColor = active + ? enabled + ? "#0c66e4" + : theme === ArThemes.DARK1 + ? darkModeColor + : color || "white" + : "#929292" + + const toolRenderWithTooltip = ( + + { + // e.preventDefault() + // e.stopPropagation() + formatter && formatter() + }} + > + setHovered(true)} + onMouseLeave={() => setHovered(false)} + > + + + {category === "color" && ( +
+ )} + + {subIcon && ( + + )} + + + {tooltip} + + ) + return popover && active ? ( + + {toolRenderWithTooltip} + {popovers(restTools, theme)[popover as "textColor" | "backgroundColor"]} + + ) : ( + toolRenderWithTooltip + ) +} + +export default TextTool diff --git a/packages/ui/src/index.scss b/packages/ui/src/index.scss new file mode 100644 index 0000000..4773767 --- /dev/null +++ b/packages/ui/src/index.scss @@ -0,0 +1,8 @@ +.ar-FlexContent { + min-height: 2.5rem; + line-height: 1.2rem; + font-family: "Noto Sans Chakma", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + &:focus-visible { + outline: none; + } +} diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json new file mode 100644 index 0000000..423c6f4 --- /dev/null +++ b/packages/ui/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "downlevelIteration": true, + "skipLibCheck": true, + "esModuleInterop": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "outDir": "build", + "resolveJsonModule": true, + "isolatedModules": true, + "declaration": true, + "noEmit": false, + "jsx": "react-jsx", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "target": "es5", + }, + "include": ["src"], + "exclude": ["build", "plop-templates", "node_modules", "src/**/*.test.*", "src/**/*.spec.*", "src/stories", "scripts"] +} diff --git a/src/packages/ui/src/index.ts b/src/packages/ui/src/index.ts deleted file mode 100644 index e69de29..0000000