tldraw
Version:
A tiny little drawing editor.
8 lines (7 loc) • 6.85 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx"],
"sourcesContent": ["import {\n\tDefaultColorStyle,\n\tSharedStyle,\n\tStyleProp,\n\tTLDefaultColorStyle,\n\tTLDefaultColorTheme,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { ReactElement, memo, useMemo, useRef } from 'react'\nimport { StyleValuesForUi } from '../../../styles'\nimport { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButton } from './Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from './Button/TldrawUiButtonIcon'\n\n/** @public */\nexport interface TLUiButtonPickerProps<T extends string> {\n\ttitle: string\n\tuiType: string\n\tstyle: StyleProp<T>\n\tvalue: SharedStyle<T>\n\titems: StyleValuesForUi<T>\n\ttheme: TLDefaultColorTheme\n\tonValueChange(style: StyleProp<T>, value: T): void\n\tonHistoryMark?(id: string): void\n}\n\n/** @public */\nexport const TldrawUiButtonPicker = memo(function TldrawUiButtonPicker<T extends string>(\n\tprops: TLUiButtonPickerProps<T>\n) {\n\tconst {\n\t\tuiType,\n\t\titems,\n\t\ttitle,\n\t\tstyle,\n\t\tvalue,\n\t\t// columns = clamp(items.length, 2, 4),\n\t\tonValueChange,\n\t\tonHistoryMark,\n\t\ttheme,\n\t} = props\n\tconst msg = useTranslation()\n\n\tconst rPointing = useRef(false)\n\tconst rPointingOriginalActiveElement = useRef<HTMLElement | null>(null)\n\n\tconst {\n\t\thandleButtonClick,\n\t\thandleButtonPointerDown,\n\t\thandleButtonPointerEnter,\n\t\thandleButtonPointerUp,\n\t} = useMemo(() => {\n\t\tconst handlePointerUp = () => {\n\t\t\trPointing.current = false\n\t\t\twindow.removeEventListener('pointerup', handlePointerUp)\n\n\t\t\t// This is fun little micro-optimization to make sure that the focus\n\t\t\t// is retained on a text label. That way, you can continue typing\n\t\t\t// after selecting a style.\n\t\t\tconst origActiveEl = rPointingOriginalActiveElement.current\n\t\t\tif (origActiveEl && ['TEXTAREA', 'INPUT'].includes(origActiveEl.nodeName)) {\n\t\t\t\torigActiveEl.focus()\n\t\t\t}\n\t\t\trPointingOriginalActiveElement.current = null\n\t\t}\n\n\t\tconst handleButtonClick = (e: React.PointerEvent<HTMLButtonElement>) => {\n\t\t\tconst { id } = e.currentTarget.dataset\n\t\t\tif (value.type === 'shared' && value.value === id) return\n\n\t\t\tonHistoryMark?.('point picker item')\n\t\t\tonValueChange(style, id as T)\n\t\t}\n\n\t\tconst handleButtonPointerDown = (e: React.PointerEvent<HTMLButtonElement>) => {\n\t\t\tconst { id } = e.currentTarget.dataset\n\n\t\t\tonHistoryMark?.('point picker item')\n\t\t\tonValueChange(style, id as T)\n\n\t\t\trPointing.current = true\n\t\t\trPointingOriginalActiveElement.current = document.activeElement as HTMLElement\n\t\t\twindow.addEventListener('pointerup', handlePointerUp) // see TLD-658\n\t\t}\n\n\t\tconst handleButtonPointerEnter = (e: React.PointerEvent<HTMLButtonElement>) => {\n\t\t\tif (!rPointing.current) return\n\n\t\t\tconst { id } = e.currentTarget.dataset\n\t\t\tonValueChange(style, id as T)\n\t\t}\n\n\t\tconst handleButtonPointerUp = (e: React.PointerEvent<HTMLButtonElement>) => {\n\t\t\tconst { id } = e.currentTarget.dataset\n\t\t\tif (value.type === 'shared' && value.value === id) return\n\n\t\t\tonValueChange(style, id as T)\n\t\t}\n\n\t\treturn {\n\t\t\thandleButtonClick,\n\t\t\thandleButtonPointerDown,\n\t\t\thandleButtonPointerEnter,\n\t\t\thandleButtonPointerUp,\n\t\t}\n\t}, [value, onHistoryMark, onValueChange, style])\n\n\treturn (\n\t\t<div data-testid={`style.${uiType}`} className={classNames('tlui-buttons__grid')}>\n\t\t\t{items.map((item) => (\n\t\t\t\t<TldrawUiButton\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\tkey={item.value}\n\t\t\t\t\tdata-id={item.value}\n\t\t\t\t\tdata-testid={`style.${uiType}.${item.value}`}\n\t\t\t\t\taria-label={item.value}\n\t\t\t\t\tdata-state={value.type === 'shared' && value.value === item.value ? 'hinted' : undefined}\n\t\t\t\t\ttitle={title + ' \u2014 ' + msg(`${uiType}-style.${item.value}` as TLUiTranslationKey)}\n\t\t\t\t\tclassName={classNames('tlui-button-grid__button')}\n\t\t\t\t\tstyle={\n\t\t\t\t\t\tstyle === (DefaultColorStyle as StyleProp<unknown>)\n\t\t\t\t\t\t\t? { color: theme[item.value as TLDefaultColorStyle].solid }\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t}\n\t\t\t\t\tonPointerEnter={handleButtonPointerEnter}\n\t\t\t\t\tonPointerDown={handleButtonPointerDown}\n\t\t\t\t\tonPointerUp={handleButtonPointerUp}\n\t\t\t\t\tonClick={handleButtonClick}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon={item.icon} />\n\t\t\t\t</TldrawUiButton>\n\t\t\t))}\n\t\t</div>\n\t)\n}) as <T extends string>(props: TLUiButtonPickerProps<T>) => ReactElement\n"],
"mappings": "AAkIK;AAlIL;AAAA,EACC;AAAA,OAKM;AACP,OAAO,gBAAgB;AACvB,SAAuB,MAAM,SAAS,cAAc;AAGpD,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AAe5B,MAAM,uBAAuB,KAAK,SAASA,sBACjD,OACC;AACD,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI;AACJ,QAAM,MAAM,eAAe;AAE3B,QAAM,YAAY,OAAO,KAAK;AAC9B,QAAM,iCAAiC,OAA2B,IAAI;AAEtE,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI,QAAQ,MAAM;AACjB,UAAM,kBAAkB,MAAM;AAC7B,gBAAU,UAAU;AACpB,aAAO,oBAAoB,aAAa,eAAe;AAKvD,YAAM,eAAe,+BAA+B;AACpD,UAAI,gBAAgB,CAAC,YAAY,OAAO,EAAE,SAAS,aAAa,QAAQ,GAAG;AAC1E,qBAAa,MAAM;AAAA,MACpB;AACA,qCAA+B,UAAU;AAAA,IAC1C;AAEA,UAAMC,qBAAoB,CAAC,MAA6C;AACvE,YAAM,EAAE,GAAG,IAAI,EAAE,cAAc;AAC/B,UAAI,MAAM,SAAS,YAAY,MAAM,UAAU,GAAI;AAEnD,sBAAgB,mBAAmB;AACnC,oBAAc,OAAO,EAAO;AAAA,IAC7B;AAEA,UAAMC,2BAA0B,CAAC,MAA6C;AAC7E,YAAM,EAAE,GAAG,IAAI,EAAE,cAAc;AAE/B,sBAAgB,mBAAmB;AACnC,oBAAc,OAAO,EAAO;AAE5B,gBAAU,UAAU;AACpB,qCAA+B,UAAU,SAAS;AAClD,aAAO,iBAAiB,aAAa,eAAe;AAAA,IACrD;AAEA,UAAMC,4BAA2B,CAAC,MAA6C;AAC9E,UAAI,CAAC,UAAU,QAAS;AAExB,YAAM,EAAE,GAAG,IAAI,EAAE,cAAc;AAC/B,oBAAc,OAAO,EAAO;AAAA,IAC7B;AAEA,UAAMC,yBAAwB,CAAC,MAA6C;AAC3E,YAAM,EAAE,GAAG,IAAI,EAAE,cAAc;AAC/B,UAAI,MAAM,SAAS,YAAY,MAAM,UAAU,GAAI;AAEnD,oBAAc,OAAO,EAAO;AAAA,IAC7B;AAEA,WAAO;AAAA,MACN,mBAAAH;AAAA,MACA,yBAAAC;AAAA,MACA,0BAAAC;AAAA,MACA,uBAAAC;AAAA,IACD;AAAA,EACD,GAAG,CAAC,OAAO,eAAe,eAAe,KAAK,CAAC;AAE/C,SACC,oBAAC,SAAI,eAAa,SAAS,MAAM,IAAI,WAAW,WAAW,oBAAoB,GAC7E,gBAAM,IAAI,CAAC,SACX;AAAA,IAAC;AAAA;AAAA,MACA,MAAK;AAAA,MAEL,WAAS,KAAK;AAAA,MACd,eAAa,SAAS,MAAM,IAAI,KAAK,KAAK;AAAA,MAC1C,cAAY,KAAK;AAAA,MACjB,cAAY,MAAM,SAAS,YAAY,MAAM,UAAU,KAAK,QAAQ,WAAW;AAAA,MAC/E,OAAO,QAAQ,aAAQ,IAAI,GAAG,MAAM,UAAU,KAAK,KAAK,EAAwB;AAAA,MAChF,WAAW,WAAW,0BAA0B;AAAA,MAChD,OACC,UAAW,oBACR,EAAE,OAAO,MAAM,KAAK,KAA4B,EAAE,MAAM,IACxD;AAAA,MAEJ,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,aAAa;AAAA,MACb,SAAS;AAAA,MAET,8BAAC,sBAAmB,MAAM,KAAK,MAAM;AAAA;AAAA,IAjBhC,KAAK;AAAA,EAkBX,CACA,GACF;AAEF,CAAC;",
"names": ["TldrawUiButtonPicker", "handleButtonClick", "handleButtonPointerDown", "handleButtonPointerEnter", "handleButtonPointerUp"]
}