@lobehub/ui 6.0.0-beta.4 → 6.0.0-beta.5
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/es/Accordion/style.d.mts +1 -1
- package/es/Anchor/Anchor.mjs +2 -2
- package/es/Anchor/Anchor.mjs.map +1 -1
- package/es/Carousel/Carousel.mjs +1 -1
- package/es/Carousel/Carousel.mjs.map +1 -1
- package/es/CodeDiff/CodeDiff.mjs.map +1 -1
- package/es/CodeDiff/PatchDiff.mjs.map +1 -1
- package/es/CodeDiff/theme.mjs.map +1 -1
- package/es/CodeDiff/type.d.mts +2 -2
- package/es/CodeEditor/CodeEditor.mjs +1 -1
- package/es/CodeEditor/CodeEditor.mjs.map +1 -1
- package/es/ColorPicker/ColorPicker.mjs +1 -1
- package/es/ColorPicker/ColorPicker.mjs.map +1 -1
- package/es/ColorSwatches/ColorSwatches.mjs +1 -1
- package/es/ColorSwatches/ColorSwatches.mjs.map +1 -1
- package/es/ConfigProvider/cdnAssets.mjs +6 -0
- package/es/ConfigProvider/cdnAssets.mjs.map +1 -0
- package/es/ConfigProvider/index.mjs +2 -1
- package/es/ConfigProvider/index.mjs.map +1 -1
- package/es/ContextMenu/store.d.mts +0 -1
- package/es/ContextMenu/store.mjs.map +1 -1
- package/es/DatePicker/DatePicker.mjs +1 -1
- package/es/DatePicker/DatePicker.mjs.map +1 -1
- package/es/DatePicker/DateRangePicker.mjs +1 -1
- package/es/DatePicker/DateRangePicker.mjs.map +1 -1
- package/es/DraggablePanel/atoms.mjs +1 -1
- package/es/DraggablePanel/atoms.mjs.map +1 -1
- package/es/DraggableSideNav/DraggableSideNav.mjs +2 -2
- package/es/DraggableSideNav/DraggableSideNav.mjs.map +1 -1
- package/es/Drawer/atoms.mjs +1 -1
- package/es/Drawer/atoms.mjs.map +1 -1
- package/es/DropdownMenu/atoms.mjs +1 -1
- package/es/DropdownMenu/atoms.mjs.map +1 -1
- package/es/EditableText/ControlInput.mjs +42 -29
- package/es/EditableText/ControlInput.mjs.map +1 -1
- package/es/EditableText/EditableText.mjs +1 -1
- package/es/EditableText/EditableText.mjs.map +1 -1
- package/es/EmojiPicker/EmojiPicker.mjs +3 -9
- package/es/EmojiPicker/EmojiPicker.mjs.map +1 -1
- package/es/EmojiPicker/useEmojiMartI18n.mjs +37 -0
- package/es/EmojiPicker/useEmojiMartI18n.mjs.map +1 -0
- package/es/FormKit/engine/tanstack.mjs +1 -1
- package/es/FormKit/engine/tanstack.mjs.map +1 -1
- package/es/HotkeyInput/HotkeyInput.mjs +1 -1
- package/es/HotkeyInput/HotkeyInput.mjs.map +1 -1
- package/es/Image/viewer/ImageViewer.mjs +1 -1
- package/es/Image/viewer/ImageViewer.mjs.map +1 -1
- package/es/ImageSelect/ImageSelect.mjs +1 -1
- package/es/ImageSelect/ImageSelect.mjs.map +1 -1
- package/es/Input/Input.mjs +7 -5
- package/es/Input/Input.mjs.map +1 -1
- package/es/Input/TextArea.mjs +1 -1
- package/es/Input/TextArea.mjs.map +1 -1
- package/es/Modal/atoms.mjs +3 -3
- package/es/Modal/atoms.mjs.map +1 -1
- package/es/Pagination/Pagination.mjs +1 -1
- package/es/Pagination/Pagination.mjs.map +1 -1
- package/es/Popover/PopoverInGroup.mjs +1 -1
- package/es/Popover/PopoverInGroup.mjs.map +1 -1
- package/es/Popover/atoms.mjs +1 -1
- package/es/Popover/atoms.mjs.map +1 -1
- package/es/Rate/Rate.mjs +1 -1
- package/es/Rate/Rate.mjs.map +1 -1
- package/es/ScrollShadow/ScrollShadow.mjs +1 -1
- package/es/ScrollShadow/ScrollShadow.mjs.map +1 -1
- package/es/SearchBar/SearchBar.mjs +31 -25
- package/es/SearchBar/SearchBar.mjs.map +1 -1
- package/es/Segmented/Segmented.mjs +1 -1
- package/es/Segmented/Segmented.mjs.map +1 -1
- package/es/Select/atoms.mjs +1 -1
- package/es/Select/atoms.mjs.map +1 -1
- package/es/Switch/atoms.mjs +1 -1
- package/es/Switch/atoms.mjs.map +1 -1
- package/es/Tabs/Tabs.mjs +35 -21
- package/es/Tabs/Tabs.mjs.map +1 -1
- package/es/Text/style.d.mts +3 -3
- package/es/ToggleGroup/ToggleGroup.mjs +1 -1
- package/es/ToggleGroup/ToggleGroup.mjs.map +1 -1
- package/es/Tooltip/TooltipInGroup.mjs +1 -1
- package/es/Tooltip/TooltipInGroup.mjs.map +1 -1
- package/es/Tooltip/TooltipStandalone.mjs +1 -1
- package/es/Tooltip/TooltipStandalone.mjs.map +1 -1
- package/es/Tree/Tree.mjs +1 -1
- package/es/Tree/Tree.mjs.map +1 -1
- package/es/awesome/Giscus/style.mjs +9 -9
- package/es/awesome/Giscus/style.mjs.map +1 -1
- package/es/awesome/GridBackground/GridBackground.mjs +1 -1
- package/es/awesome/GridBackground/GridBackground.mjs.map +1 -1
- package/es/awesome/GridBackground/GridShowcase.mjs +4 -4
- package/es/awesome/GridBackground/GridShowcase.mjs.map +1 -1
- package/es/awesome/Spline/ParentSize.mjs +1 -1
- package/es/awesome/Spline/ParentSize.mjs.map +1 -1
- package/es/chat/BackBottom/BackBottom.mjs +1 -1
- package/es/chat/BackBottom/BackBottom.mjs.map +1 -1
- package/es/chat/BackBottom/type.d.mts +2 -2
- package/es/chat/EditableMessage/EditableMessage.mjs +1 -1
- package/es/chat/EditableMessage/EditableMessage.mjs.map +1 -1
- package/es/chat/EditableMessageList/EditableMessageList.mjs +1 -1
- package/es/chat/EditableMessageList/EditableMessageList.mjs.map +1 -1
- package/es/chat/EditableMessageList/messageReducer.mjs +30 -23
- package/es/chat/EditableMessageList/messageReducer.mjs.map +1 -1
- package/es/chat/MessageModal/MessageModal.mjs +1 -1
- package/es/chat/MessageModal/MessageModal.mjs.map +1 -1
- package/es/chat/TokenTag/TokenTag.mjs +2 -3
- package/es/chat/TokenTag/TokenTag.mjs.map +1 -1
- package/es/hooks/useControlledState.mjs +20 -0
- package/es/hooks/useControlledState.mjs.map +1 -0
- package/es/hooks/useHighlight.mjs +2 -2
- package/es/hooks/useHighlight.mjs.map +1 -1
- package/es/hooks/useHover.mjs +22 -0
- package/es/hooks/useHover.mjs.map +1 -0
- package/es/hooks/useScroll.d.mts +8 -0
- package/es/hooks/useScroll.mjs +33 -0
- package/es/hooks/useScroll.mjs.map +1 -0
- package/es/hooks/useSize.mjs +26 -0
- package/es/hooks/useSize.mjs.map +1 -0
- package/es/internal/virtual/VirtualScrollArea.mjs +1 -1
- package/es/internal/virtual/VirtualScrollArea.mjs.map +1 -1
- package/es/mobile/ChatInputArea/ChatInputArea.mjs +1 -1
- package/es/mobile/ChatInputArea/ChatInputArea.mjs.map +1 -1
- package/es/mobile/TabBar/TabBar.mjs +1 -1
- package/es/mobile/TabBar/TabBar.mjs.map +1 -1
- package/es/node_modules/.pnpm/@eslint_core@1.2.1/node_modules/@eslint/core/dist/esm/types.d.mts +2 -46
- package/es/node_modules/.pnpm/@eslint_plugin-kit@0.7.3/node_modules/@eslint/plugin-kit/dist/cjs/index.d.mts +1 -1
- package/es/node_modules/.pnpm/@types_estree@1.0.9/node_modules/@types/estree/index.d.mts +1 -4
- package/es/node_modules/.pnpm/eslint@10.12.0_jiti@2.6.1_supports-color@10.2.2/node_modules/eslint/lib/types/index.d.mts +1 -1
- package/es/styles/theme/token/neutral.mjs +5 -5
- package/es/styles/theme/token/neutral.mjs.map +1 -1
- package/es/utils/colorMath.mjs +52 -0
- package/es/utils/colorMath.mjs.map +1 -0
- package/es/utils/formatNumber.mjs +7 -0
- package/es/utils/formatNumber.mjs.map +1 -0
- package/es/utils/genCdnUrl.mjs +6 -3
- package/es/utils/genCdnUrl.mjs.map +1 -1
- package/es/utils/hashString.mjs +19 -0
- package/es/utils/hashString.mjs.map +1 -0
- package/es/utils/mergeRefs.mjs +20 -0
- package/es/utils/mergeRefs.mjs.map +1 -0
- package/es/utils/placement.d.mts +5 -5
- package/es/utils/placement.mjs.map +1 -1
- package/package.json +16 -42
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import Button from "../../Button/Button.mjs";
|
|
3
3
|
import FlexBasic_default from "../../Flex/FlexBasic.mjs";
|
|
4
4
|
import { useResponsive } from "../../styles/theme/scope.mjs";
|
|
5
|
+
import { useControlledState } from "../../hooks/useControlledState.mjs";
|
|
5
6
|
import { useTranslation } from "../../i18n/useTranslation.mjs";
|
|
6
7
|
import TextArea_default from "../../Input/TextArea.mjs";
|
|
7
8
|
import CodeEditor from "../../CodeEditor/CodeEditor.mjs";
|
|
@@ -11,7 +12,6 @@ import { styles, textAreaStyle } from "../MessageInput/style.mjs";
|
|
|
11
12
|
import messageModal_default from "../../i18n/resources/en/messageModal.mjs";
|
|
12
13
|
import { memo, useState } from "react";
|
|
13
14
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
-
import useControlledState from "use-merge-value";
|
|
15
15
|
//#region src/chat/MessageModal/MessageModal.tsx
|
|
16
16
|
const MessageModal = memo(({ editing, open, height = "75vh", onOpenChange, onEditingChange, placeholder, value, language = "markdown", onChange, text, footer, extra }) => {
|
|
17
17
|
const { mobile } = useResponsive();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageModal.mjs","names":["messageModalMessages","Flexbox","TextArea","textStyles"],"sources":["../../../src/chat/MessageModal/MessageModal.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useState } from 'react';\
|
|
1
|
+
{"version":3,"file":"MessageModal.mjs","names":["messageModalMessages","Flexbox","TextArea","textStyles"],"sources":["../../../src/chat/MessageModal/MessageModal.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useState } from 'react';\n\nimport Button from '@/Button';\nimport { styles as textStyles, textAreaStyle } from '@/chat/MessageInput/style';\nimport CodeEditor from '@/CodeEditor';\nimport { Flexbox } from '@/Flex';\nimport { useControlledState } from '@/hooks/useControlledState';\nimport messageModalMessages from '@/i18n/resources/en/messageModal';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport { TextArea } from '@/Input';\nimport Markdown from '@/Markdown';\nimport { Modal } from '@/Modal';\nimport { useResponsive } from '@/styles/theme/scope';\n\nimport { type MessageModalProps } from './type';\n\nconst MessageModal = memo<MessageModalProps>(\n ({\n editing,\n open,\n height = '75vh',\n onOpenChange,\n onEditingChange,\n placeholder,\n value,\n language = 'markdown',\n onChange,\n text,\n footer,\n extra,\n }) => {\n const { mobile } = useResponsive();\n const { t } = useTranslation(messageModalMessages);\n const [isEdit, setTyping] = useControlledState(false, {\n onChange: onEditingChange,\n value: editing,\n });\n\n const [showModal, setShowModal] = useControlledState(false, {\n onChange: onOpenChange,\n value: open,\n });\n\n const [temporaryValue, setMessage] = useState(value);\n\n const confirmText = text?.confirm ?? t('messageModal.confirm');\n const cancelText = text?.cancel ?? t('messageModal.cancel');\n const editText = text?.edit ?? t('messageModal.edit');\n\n const modalFooter = isEdit ? (\n <Flexbox direction={'horizontal-reverse'} gap={8}>\n <Button\n type=\"primary\"\n onClick={() => {\n setTyping(false);\n onChange?.(temporaryValue);\n setMessage(value);\n }}\n >\n {confirmText}\n </Button>\n <Button\n onClick={() => {\n setTyping(false);\n setMessage(value);\n }}\n >\n {cancelText}\n </Button>\n </Flexbox>\n ) : (\n footer\n );\n\n return (\n <Modal\n allowFullscreen\n destroyOnHidden\n cancelText={cancelText}\n footer={modalFooter}\n height={height}\n okText={editText}\n open={showModal}\n title={text?.title}\n onOk={() => setTyping(true)}\n onCancel={() => {\n setShowModal(false);\n setTyping(false);\n setMessage(value);\n }}\n >\n {isEdit ? (\n mobile ? (\n <TextArea\n autoSize\n className={textStyles}\n defaultValue={temporaryValue}\n placeholder={placeholder}\n style={textAreaStyle}\n value={temporaryValue}\n variant={'borderless'}\n onBlur={(e) => setMessage(e.target.value)}\n onChange={(value) => setMessage(value.target.value)}\n />\n ) : (\n <CodeEditor\n className={textStyles}\n defaultValue={temporaryValue}\n language={language}\n placeholder={placeholder}\n value={temporaryValue}\n variant={'borderless'}\n onBlur={(e) => setMessage(e.target.value)}\n onValueChange={(value) => setMessage(value)}\n />\n )\n ) : (\n <>\n {extra}\n <Markdown variant={'chat'}>{String(value || placeholder)}</Markdown>\n </>\n )}\n </Modal>\n );\n },\n);\n\nMessageModal.displayName = 'MessageModal';\n\nexport default MessageModal;\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,MAAM,eAAe,MAClB,EACC,SACA,MACA,SAAS,QACT,cACA,iBACA,aACA,OACA,WAAW,YACX,UACA,MACA,QACA,YACI;CACJ,MAAM,EAAE,WAAW,cAAc;CACjC,MAAM,EAAE,MAAM,eAAeA,oBAAoB;CACjD,MAAM,CAAC,QAAQ,aAAa,mBAAmB,OAAO;EACpD,UAAU;EACV,OAAO;CACT,CAAC;CAED,MAAM,CAAC,WAAW,gBAAgB,mBAAmB,OAAO;EAC1D,UAAU;EACV,OAAO;CACT,CAAC;CAED,MAAM,CAAC,gBAAgB,cAAc,SAAS,KAAK;CAEnD,MAAM,cAAc,MAAM,WAAW,EAAE,sBAAsB;CAC7D,MAAM,aAAa,MAAM,UAAU,EAAE,qBAAqB;CAC1D,MAAM,WAAW,MAAM,QAAQ,EAAE,mBAAmB;CA2BpD,OACE,oBAAC,OAAD;EACE,iBAAA;EACA,iBAAA;EACY;EACZ,QA9BgB,SAClB,qBAACC,mBAAD;GAAS,WAAW;GAAsB,KAAK;GAA/C,UAAA,CACE,oBAAC,QAAD;IACE,MAAK;IACL,eAAe;KACb,UAAU,KAAK;KACf,WAAW,cAAc;KACzB,WAAW,KAAK;IAClB;IAEC,UAAA;GACK,CAAA,GACR,oBAAC,QAAD;IACE,eAAe;KACb,UAAU,KAAK;KACf,WAAW,KAAK;IAClB;IAEC,UAAA;GACK,CAAA,CACD;EAET,CAAA,IAAA;EASU;EACR,QAAQ;EACR,MAAM;EACN,OAAO,MAAM;EACb,YAAY,UAAU,IAAI;EAC1B,gBAAgB;GACd,aAAa,KAAK;GAClB,UAAU,KAAK;GACf,WAAW,KAAK;EAClB;EAEC,UAAA,SACC,SACE,oBAACC,kBAAD;GACE,UAAA;GACA,WAAWC;GACX,cAAc;GACD;GACb,OAAO;GACP,OAAO;GACP,SAAS;GACT,SAAS,MAAM,WAAW,EAAE,OAAO,KAAK;GACxC,WAAW,UAAU,WAAW,MAAM,OAAO,KAAK;EACnD,CAAA,IAED,oBAAC,YAAD;GACE,WAAWA;GACX,cAAc;GACJ;GACG;GACb,OAAO;GACP,SAAS;GACT,SAAS,MAAM,WAAW,EAAE,OAAO,KAAK;GACxC,gBAAgB,UAAU,WAAW,KAAK;EAC3C,CAAA,IAGH,qBAAA,YAAA,EAAA,UAAA,CACG,OACD,oBAAC,UAAD;GAAU,SAAS;GAAS,UAAA,OAAO,SAAS,WAAW;EAAY,CAAA,CACnE,EAAA,CAAA;CAEC,CAAA;AAEX,CACF;AAEA,aAAa,cAAc"}
|
|
@@ -4,11 +4,10 @@ import ActionIcon from "../../ActionIcon/ActionIcon.mjs";
|
|
|
4
4
|
import { useTranslation } from "../../i18n/useTranslation.mjs";
|
|
5
5
|
import Progress from "../../Progress/Progress.mjs";
|
|
6
6
|
import chat_default from "../../i18n/resources/en/chat.mjs";
|
|
7
|
+
import { formatNumber } from "../../utils/formatNumber.mjs";
|
|
7
8
|
import { useMemo } from "react";
|
|
8
9
|
import { jsx } from "react/jsx-runtime";
|
|
9
|
-
import numeral from "numeral";
|
|
10
10
|
//#region src/chat/TokenTag/TokenTag.tsx
|
|
11
|
-
const format = (number) => numeral(number).format("0,0");
|
|
12
11
|
const TokenTag = ({ mode = "remained", maxValue, value, text, showInfo, size = 20, ...rest }) => {
|
|
13
12
|
const { t } = useTranslation(chat_default);
|
|
14
13
|
const valueLeft = maxValue - value;
|
|
@@ -34,7 +33,7 @@ const TokenTag = ({ mode = "remained", maxValue, value, text, showInfo, size = 2
|
|
|
34
33
|
type
|
|
35
34
|
};
|
|
36
35
|
}, [percent]);
|
|
37
|
-
const title = valueLeft > 0 ? [mode === "remained" ? remainedText : usedText, mode === "remained" ?
|
|
36
|
+
const title = valueLeft > 0 ? [mode === "remained" ? remainedText : usedText, mode === "remained" ? formatNumber(valueLeft) : formatNumber(value)].join(" ") : overloadText;
|
|
38
37
|
return /* @__PURE__ */ jsx(ActionIcon, {
|
|
39
38
|
size,
|
|
40
39
|
title: showInfo ? title : void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenTag.mjs","names":["chatMessages"],"sources":["../../../src/chat/TokenTag/TokenTag.tsx"],"sourcesContent":["'use client';\n\nimport
|
|
1
|
+
{"version":3,"file":"TokenTag.mjs","names":["chatMessages"],"sources":["../../../src/chat/TokenTag/TokenTag.tsx"],"sourcesContent":["'use client';\n\nimport { type FC, useMemo } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport chatMessages from '@/i18n/resources/en/chat';\nimport { useTranslation } from '@/i18n/useTranslation';\nimport Progress from '@/Progress';\nimport { cssVar } from '@/styles/stylex/cssVar.stylex';\nimport { formatNumber } from '@/utils/formatNumber';\n\nimport type { TokenTagProps } from './type';\n\nconst TokenTag: FC<TokenTagProps> = ({\n mode = 'remained',\n maxValue,\n value,\n text,\n showInfo,\n size = 20,\n ...rest\n}) => {\n const { t } = useTranslation(chatMessages);\n const valueLeft = maxValue - value;\n const percent = value / maxValue;\n const remainedText = text?.remained ?? t('tokenTag.remained');\n const usedText = text?.used ?? t('tokenTag.used');\n const overloadText = text?.overload ?? t('tokenTag.overload');\n\n const data = useMemo(() => {\n let type: 'normal' | 'low' | 'overload';\n let color;\n\n if (percent < 0.7) {\n type = 'normal';\n color = cssVar.colorText;\n } else if (percent < 0.9) {\n type = 'low';\n color = cssVar.colorWarning;\n } else {\n type = 'overload';\n color = cssVar.colorError;\n }\n return {\n color,\n type,\n };\n }, [percent]);\n\n const title =\n valueLeft > 0\n ? [\n mode === 'remained' ? remainedText : usedText,\n mode === 'remained' ? formatNumber(valueLeft) : formatNumber(value),\n ].join(' ')\n : overloadText;\n\n return (\n <ActionIcon\n size={size}\n title={showInfo ? title : undefined}\n icon={\n <Progress\n percent={percent * 100}\n showInfo={false}\n size={Number(typeof size === 'object' ? size?.size || 20 : size) || 20}\n strokeColor={data.color}\n type=\"circle\"\n />\n }\n {...rest}\n />\n );\n};\n\nTokenTag.displayName = 'TokenTag';\n\nexport default TokenTag;\n"],"mappings":";;;;;;;;;;AAaA,MAAM,YAA+B,EACnC,OAAO,YACP,UACA,OACA,MACA,UACA,OAAO,IACP,GAAG,WACC;CACJ,MAAM,EAAE,MAAM,eAAeA,YAAY;CACzC,MAAM,YAAY,WAAW;CAC7B,MAAM,UAAU,QAAQ;CACxB,MAAM,eAAe,MAAM,YAAY,EAAE,mBAAmB;CAC5D,MAAM,WAAW,MAAM,QAAQ,EAAE,eAAe;CAChD,MAAM,eAAe,MAAM,YAAY,EAAE,mBAAmB;CAE5D,MAAM,OAAO,cAAc;EACzB,IAAI;EACJ,IAAI;EAEJ,IAAI,UAAU,IAAK;GACjB,OAAO;GACP,QAAQ,OAAO;EACjB,OAAO,IAAI,UAAU,IAAK;GACxB,OAAO;GACP,QAAQ,OAAO;EACjB,OAAO;GACL,OAAO;GACP,QAAQ,OAAO;EACjB;EACA,OAAO;GACL;GACA;EACF;CACF,GAAG,CAAC,OAAO,CAAC;CAEZ,MAAM,QACJ,YAAY,IACR,CACE,SAAS,aAAa,eAAe,UACrC,SAAS,aAAa,aAAa,SAAS,IAAI,aAAa,KAAK,CACpE,CAAC,CAAC,KAAK,GAAG,IACV;CAEN,OACE,oBAAC,YAAD;EACQ;EACN,OAAO,WAAW,QAAQ,KAAA;EAC1B,MACE,oBAAC,UAAD;GACE,SAAS,UAAU;GACnB,UAAU;GACV,MAAM,OAAO,OAAO,SAAS,WAAW,MAAM,QAAQ,KAAK,IAAI,KAAK;GACpE,aAAa,KAAK;GAClB,MAAK;EACN,CAAA;EAEH,GAAI;CACL,CAAA;AAEL;AAEA,SAAS,cAAc"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useEventCallback } from "./useEventCallback.mjs";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
//#region src/hooks/useControlledState.ts
|
|
4
|
+
const resolveInitial = (initial) => typeof initial === "function" ? initial() : initial;
|
|
5
|
+
const useControlledState = (defaultStateValue, { defaultValue, onChange, value } = {}) => {
|
|
6
|
+
const [innerValue, setInnerValue] = useState(() => {
|
|
7
|
+
if (value !== void 0) return value;
|
|
8
|
+
if (defaultValue !== void 0) return resolveInitial(defaultValue);
|
|
9
|
+
return resolveInitial(defaultStateValue);
|
|
10
|
+
});
|
|
11
|
+
const mergedValue = value === void 0 ? innerValue : value;
|
|
12
|
+
return [mergedValue, useEventCallback((next) => {
|
|
13
|
+
setInnerValue(next);
|
|
14
|
+
if (mergedValue !== next) onChange?.(next, mergedValue);
|
|
15
|
+
})];
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { useControlledState };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=useControlledState.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useControlledState.mjs","names":[],"sources":["../../src/hooks/useControlledState.ts"],"sourcesContent":["import { useState } from 'react';\n\nimport { useEventCallback } from './useEventCallback';\n\ntype Initial<T> = T | (() => T);\n\nexport interface ControlledStateOptions<T> {\n defaultValue?: Initial<T>;\n onChange?: (value: T, prevValue: T) => void;\n value?: T;\n}\n\nconst resolveInitial = <T>(initial: Initial<T>): T =>\n typeof initial === 'function' ? (initial as () => T)() : initial;\n\nexport const useControlledState = <T>(\n defaultStateValue: Initial<T>,\n { defaultValue, onChange, value }: ControlledStateOptions<T> = {},\n): [T, (next: T) => void] => {\n const [innerValue, setInnerValue] = useState<T>(() => {\n if (value !== undefined) return value;\n if (defaultValue !== undefined) return resolveInitial(defaultValue);\n return resolveInitial(defaultStateValue);\n });\n\n const mergedValue = value === undefined ? innerValue : value;\n\n const setValue = useEventCallback((next: T) => {\n setInnerValue(next);\n if (mergedValue !== next) onChange?.(next, mergedValue);\n });\n\n return [mergedValue, setValue];\n};\n"],"mappings":";;;AAYA,MAAM,kBAAqB,YACzB,OAAO,YAAY,aAAc,QAAoB,IAAI;AAE3D,MAAa,sBACX,mBACA,EAAE,cAAc,UAAU,UAAqC,CAAC,MACrC;CAC3B,MAAM,CAAC,YAAY,iBAAiB,eAAkB;EACpD,IAAI,UAAU,KAAA,GAAW,OAAO;EAChC,IAAI,iBAAiB,KAAA,GAAW,OAAO,eAAe,YAAY;EAClE,OAAO,eAAe,iBAAiB;CACzC,CAAC;CAED,MAAM,cAAc,UAAU,KAAA,IAAY,aAAa;CAOvD,OAAO,CAAC,aALS,kBAAkB,SAAY;EAC7C,cAAc,IAAI;EAClB,IAAI,gBAAgB,MAAM,WAAW,MAAM,WAAW;CACxD,CAE4B,CAAC;AAC/B"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import lobe_theme_default from "../Highlighter/theme/lobe-theme.mjs";
|
|
3
3
|
import { getCodeLanguageByInput } from "../Highlighter/const.mjs";
|
|
4
|
+
import { hashString } from "../utils/hashString.mjs";
|
|
4
5
|
import { useEffect, useMemo, useState } from "react";
|
|
5
6
|
import { transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationWordHighlight } from "@shikijs/transformers";
|
|
6
|
-
import { Md5 } from "ts-md5";
|
|
7
7
|
//#region src/hooks/useHighlight.ts
|
|
8
8
|
const MD5_LENGTH_THRESHOLD = 1e4;
|
|
9
9
|
const highlightCache = /* @__PURE__ */ new Map();
|
|
@@ -46,7 +46,7 @@ const useHighlight = (text, { language, enableTransformer, theme: builtinTheme,
|
|
|
46
46
|
}, [enableTransformer]);
|
|
47
47
|
const cacheKey = useMemo(() => {
|
|
48
48
|
if (streaming) return null;
|
|
49
|
-
const hash = safeText.length < 1e4 ? safeText :
|
|
49
|
+
const hash = safeText.length < 1e4 ? safeText : `${safeText.length}:${hashString(safeText)}`;
|
|
50
50
|
return [
|
|
51
51
|
matchedLanguage,
|
|
52
52
|
builtinTheme,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHighlight.mjs","names":["lobeTheme"],"sources":["../../src/hooks/useHighlight.ts"],"sourcesContent":["'use client';\n\nimport {\n transformerNotationDiff,\n transformerNotationErrorLevel,\n transformerNotationFocus,\n transformerNotationHighlight,\n transformerNotationWordHighlight,\n} from '@shikijs/transformers';\nimport { type CSSProperties, useEffect, useMemo, useState } from 'react';\nimport type { BuiltinTheme, CodeToHastOptions, ThemedToken } from 'shiki';\
|
|
1
|
+
{"version":3,"file":"useHighlight.mjs","names":["lobeTheme"],"sources":["../../src/hooks/useHighlight.ts"],"sourcesContent":["'use client';\n\nimport {\n transformerNotationDiff,\n transformerNotationErrorLevel,\n transformerNotationFocus,\n transformerNotationHighlight,\n transformerNotationWordHighlight,\n} from '@shikijs/transformers';\nimport { type CSSProperties, useEffect, useMemo, useState } from 'react';\nimport type { BuiltinTheme, CodeToHastOptions, ThemedToken } from 'shiki';\n\nimport { getCodeLanguageByInput } from '@/Highlighter/const';\nimport lobeTheme from '@/Highlighter/theme/lobe-theme';\nimport { hashString } from '@/utils/hashString';\n\n// Application-level cache to avoid repeated calculations\nexport const MD5_LENGTH_THRESHOLD = 10_000;\n\nexport type StreamingHighlightResult = {\n lines: ThemedToken[][];\n preStyle?: CSSProperties;\n};\n\n// Application-level cache for highlighted HTML\n// Key: cacheKey string, Value: Promise<string>\nconst highlightCache = new Map<string, Promise<string>>();\n\n// Maximum cache size to prevent memory leaks\nconst MAX_CACHE_SIZE = 1000;\n\n// Clean up old cache entries when limit is reached\nconst cleanupCache = () => {\n if (highlightCache.size > MAX_CACHE_SIZE) {\n // Remove oldest 20% of entries\n const entriesToRemove = Math.floor(MAX_CACHE_SIZE * 0.2);\n const keysToRemove = Array.from(highlightCache.keys()).slice(0, entriesToRemove);\n for (const key of keysToRemove) {\n highlightCache.delete(key);\n }\n }\n};\n\nexport type ICodeToHtml = (code: string, options: CodeToHastOptions) => Promise<string>;\nexport type ShikiModule = typeof import('shiki');\n\n// Use codeToHtml shorthand for better performance\n// It automatically manages highlighter instances and loads themes/languages on-demand\nlet codeToHtmlPromise: Promise<ICodeToHtml | null> | null = null;\n\nconst loadCodeToHtml = (): Promise<ICodeToHtml | null> => {\n if (typeof window === 'undefined') return Promise.resolve(null);\n\n if (!codeToHtmlPromise) {\n codeToHtmlPromise = import('shiki').then((mod) => mod.codeToHtml ?? null);\n }\n\n return codeToHtmlPromise;\n};\n\n// Export shikiModulePromise for useStreamHighlight compatibility\nconst loadShikiModule = (): Promise<ShikiModule | null> => {\n if (typeof window === 'undefined') return Promise.resolve(null);\n return import('shiki');\n};\nexport const shikiModulePromise = loadShikiModule();\n\n// Helper function: Safe HTML escaping\nexport const escapeHtml = (str: string): string => {\n return str\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n};\n\n// Main highlight component - optimized version without SWR\nconst customThemes = {\n 'lobe-theme': lobeTheme,\n};\n\nexport const useHighlight = (\n text: string,\n {\n language,\n enableTransformer,\n theme: builtinTheme,\n streaming,\n }: { enableTransformer?: boolean; language: string; streaming?: boolean; theme?: BuiltinTheme },\n): string => {\n // Safely handle language and text with boundary checks\n const safeText = text ?? '';\n const lang = (language ?? 'plaintext').toLowerCase();\n\n // Match supported languages\n const matchedLanguage = useMemo(() => getCodeLanguageByInput(lang), [lang]);\n\n // Optimize transformer creation\n const transformers = useMemo(() => {\n if (!enableTransformer) return;\n return [\n transformerNotationDiff(),\n transformerNotationHighlight(),\n transformerNotationWordHighlight(),\n transformerNotationFocus(),\n transformerNotationErrorLevel(),\n ];\n }, [enableTransformer]);\n\n // Build cache key\n const cacheKey = useMemo((): string | null => {\n if (streaming) return null;\n // Use hash for long text\n const hash =\n safeText.length < MD5_LENGTH_THRESHOLD\n ? safeText\n : `${safeText.length}:${hashString(safeText)}`;\n return [matchedLanguage, builtinTheme, hash].filter(Boolean).join('-');\n }, [safeText, matchedLanguage, builtinTheme, streaming]);\n\n const [data, setData] = useState<string | undefined>();\n\n useEffect(() => {\n if (!cacheKey) {\n setData(undefined);\n return;\n }\n\n // Check cache first\n const cachedPromise = highlightCache.get(cacheKey);\n if (cachedPromise) {\n cachedPromise\n .then((html) => {\n setData(html);\n })\n .catch(() => {\n // Silently handle errors, fallback will be handled in the promise\n });\n return;\n }\n\n // Create new promise for highlighting\n // Using codeToHtml shorthand: automatically loads themes/languages on-demand\n const highlightPromise = (async (): Promise<string> => {\n try {\n // Try full rendering with transformers\n const shikiModule = await shikiModulePromise;\n if (!shikiModule) return safeText;\n\n const effectiveTheme = builtinTheme || 'lobe-theme';\n\n // Load custom theme if using slack-dark or slack-ochin\n if (!builtinTheme && effectiveTheme === 'lobe-theme') {\n const customTheme = customThemes[effectiveTheme];\n if (customTheme) {\n // Use getSingletonHighlighter to load custom theme\n const highlighter = await shikiModule.getSingletonHighlighter({\n langs: [matchedLanguage],\n themes: [customTheme as any],\n });\n\n const html = await highlighter.codeToHtml(safeText, {\n lang: matchedLanguage,\n theme: effectiveTheme,\n transformers,\n });\n\n return html;\n }\n }\n\n // Fallback to codeToHtml for builtin themes\n const codeToHtml = await loadCodeToHtml();\n if (!codeToHtml) return safeText;\n\n const html = await codeToHtml(safeText, {\n lang: matchedLanguage,\n theme: effectiveTheme,\n transformers,\n });\n\n return html;\n } catch (error_) {\n console.error('Advanced rendering failed:', error_);\n\n try {\n // Try simple rendering (without transformers)\n const codeToHtml = await loadCodeToHtml();\n if (!codeToHtml) return safeText;\n const html = await codeToHtml(safeText, {\n lang: matchedLanguage,\n theme: 'lobe-theme',\n });\n return html;\n } catch {\n // Fallback to plain text\n const fallbackHtml = `<pre class=\"fallback\"><code>${escapeHtml(safeText)}</code></pre>`;\n return fallbackHtml;\n }\n }\n })();\n\n // Cache the promise\n highlightCache.set(cacheKey, highlightPromise);\n cleanupCache();\n\n // Handle promise result\n highlightPromise\n .then((html) => {\n // Only update if this is still the current cache key\n if (highlightCache.get(cacheKey) === highlightPromise) {\n setData(html);\n }\n })\n .catch(() => {\n // Remove failed promise from cache\n if (highlightCache.get(cacheKey) === highlightPromise) {\n highlightCache.delete(cacheKey);\n }\n });\n }, [cacheKey, safeText, matchedLanguage, builtinTheme, transformers, customThemes]);\n\n return data || '';\n};\n"],"mappings":";;;;;;;AAiBA,MAAa,uBAAuB;AASpC,MAAM,iCAAiB,IAAI,IAA6B;AAGxD,MAAM,iBAAiB;AAGvB,MAAM,qBAAqB;CACzB,IAAI,eAAe,OAAO,gBAAgB;EAExC,MAAM,kBAAkB,KAAK,MAAM,iBAAiB,EAAG;EACvD,MAAM,eAAe,MAAM,KAAK,eAAe,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,eAAe;EAC/E,KAAK,MAAM,OAAO,cAChB,eAAe,OAAO,GAAG;CAE7B;AACF;AAOA,IAAI,oBAAwD;AAE5D,MAAM,uBAAoD;CACxD,IAAI,OAAO,WAAW,aAAa,OAAO,QAAQ,QAAQ,IAAI;CAE9D,IAAI,CAAC,mBACH,oBAAoB,OAAO,QAAQ,CAAC,MAAM,QAAQ,IAAI,cAAc,IAAI;CAG1E,OAAO;AACT;AAGA,MAAM,wBAAqD;CACzD,IAAI,OAAO,WAAW,aAAa,OAAO,QAAQ,QAAQ,IAAI;CAC9D,OAAO,OAAO;AAChB;AACA,MAAa,qBAAqB,gBAAgB;AAGlD,MAAa,cAAc,QAAwB;CACjD,OAAO,IACJ,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,MAAK,QAAQ,CAAC,CACzB,WAAW,KAAK,QAAQ;AAC7B;AAGA,MAAM,eAAe,EACnB,cAAcA,mBAChB;AAEA,MAAa,gBACX,MACA,EACE,UACA,mBACA,OAAO,cACP,gBAES;CAEX,MAAM,WAAW,QAAQ;CACzB,MAAM,QAAQ,YAAY,YAAA,CAAa,YAAY;CAGnD,MAAM,kBAAkB,cAAc,uBAAuB,IAAI,GAAG,CAAC,IAAI,CAAC;CAG1E,MAAM,eAAe,cAAc;EACjC,IAAI,CAAC,mBAAmB;EACxB,OAAO;GACL,wBAAwB;GACxB,6BAA6B;GAC7B,iCAAiC;GACjC,yBAAyB;GACzB,8BAA8B;EAChC;CACF,GAAG,CAAC,iBAAiB,CAAC;CAGtB,MAAM,WAAW,cAA6B;EAC5C,IAAI,WAAW,OAAO;EAEtB,MAAM,OACJ,SAAS,SAAA,MACL,WACA,GAAG,SAAS,OAAO,GAAG,WAAW,QAAQ;EAC/C,OAAO;GAAC;GAAiB;GAAc;EAAI,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CACvE,GAAG;EAAC;EAAU;EAAiB;EAAc;CAAS,CAAC;CAEvD,MAAM,CAAC,MAAM,WAAW,SAA6B;CAErD,gBAAgB;EACd,IAAI,CAAC,UAAU;GACb,QAAQ,KAAA,CAAS;GACjB;EACF;EAGA,MAAM,gBAAgB,eAAe,IAAI,QAAQ;EACjD,IAAI,eAAe;GACjB,cACG,MAAM,SAAS;IACd,QAAQ,IAAI;GACd,CAAC,CAAC,CACD,YAAY,CAEb,CAAC;GACH;EACF;EAIA,MAAM,oBAAoB,YAA6B;GACrD,IAAI;IAEF,MAAM,cAAc,MAAM;IAC1B,IAAI,CAAC,aAAa,OAAO;IAEzB,MAAM,iBAAiB,gBAAgB;IAGvC,IAAI,CAAC,gBAAgB,mBAAmB,cAAc;KACpD,MAAM,cAAc,aAAa;KACjC,IAAI,aAaF,OAAO,OANY,MALO,YAAY,wBAAwB;MAC5D,OAAO,CAAC,eAAe;MACvB,QAAQ,CAAC,WAAkB;KAC7B,CAAC,EAAA,CAE8B,WAAW,UAAU;MAClD,MAAM;MACN,OAAO;MACP;KACF,CAAC;IAIL;IAGA,MAAM,aAAa,MAAM,eAAe;IACxC,IAAI,CAAC,YAAY,OAAO;IAQxB,OAAO,MANY,WAAW,UAAU;KACtC,MAAM;KACN,OAAO;KACP;IACF,CAAC;GAGH,SAAS,QAAQ;IACf,QAAQ,MAAM,8BAA8B,MAAM;IAElD,IAAI;KAEF,MAAM,aAAa,MAAM,eAAe;KACxC,IAAI,CAAC,YAAY,OAAO;KAKxB,OAAO,MAJY,WAAW,UAAU;MACtC,MAAM;MACN,OAAO;KACT,CAAC;IAEH,QAAQ;KAGN,OAAO,+BAD6C,WAAW,QAAQ,EAAE;IAE3E;GACF;EACF,EAAA,CAAG;EAGH,eAAe,IAAI,UAAU,gBAAgB;EAC7C,aAAa;EAGb,iBACG,MAAM,SAAS;GAEd,IAAI,eAAe,IAAI,QAAQ,MAAM,kBACnC,QAAQ,IAAI;EAEhB,CAAC,CAAC,CACD,YAAY;GAEX,IAAI,eAAe,IAAI,QAAQ,MAAM,kBACnC,eAAe,OAAO,QAAQ;EAElC,CAAC;CACL,GAAG;EAAC;EAAU;EAAU;EAAiB;EAAc;EAAc;CAAY,CAAC;CAElF,OAAO,QAAQ;AACjB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
//#region src/hooks/useHover.ts
|
|
3
|
+
const useHover = (ref) => {
|
|
4
|
+
const [hovering, setHovering] = useState(false);
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const element = ref.current;
|
|
7
|
+
if (!element) return;
|
|
8
|
+
const enter = () => setHovering(true);
|
|
9
|
+
const leave = () => setHovering(false);
|
|
10
|
+
element.addEventListener("mouseenter", enter);
|
|
11
|
+
element.addEventListener("mouseleave", leave);
|
|
12
|
+
return () => {
|
|
13
|
+
element.removeEventListener("mouseenter", enter);
|
|
14
|
+
element.removeEventListener("mouseleave", leave);
|
|
15
|
+
};
|
|
16
|
+
}, [ref]);
|
|
17
|
+
return hovering;
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { useHover };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=useHover.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useHover.mjs","names":[],"sources":["../../src/hooks/useHover.ts"],"sourcesContent":["import { type RefObject, useEffect, useState } from 'react';\n\nexport const useHover = (ref: RefObject<Element | null>): boolean => {\n const [hovering, setHovering] = useState(false);\n\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n const enter = () => setHovering(true);\n const leave = () => setHovering(false);\n element.addEventListener('mouseenter', enter);\n element.addEventListener('mouseleave', leave);\n return () => {\n element.removeEventListener('mouseenter', enter);\n element.removeEventListener('mouseleave', leave);\n };\n }, [ref]);\n\n return hovering;\n};\n"],"mappings":";;AAEA,MAAa,YAAY,QAA4C;CACnE,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAE9C,gBAAgB;EACd,MAAM,UAAU,IAAI;EACpB,IAAI,CAAC,SAAS;EACd,MAAM,cAAc,YAAY,IAAI;EACpC,MAAM,cAAc,YAAY,KAAK;EACrC,QAAQ,iBAAiB,cAAc,KAAK;EAC5C,QAAQ,iBAAiB,cAAc,KAAK;EAC5C,aAAa;GACX,QAAQ,oBAAoB,cAAc,KAAK;GAC/C,QAAQ,oBAAoB,cAAc,KAAK;EACjD;CACF,GAAG,CAAC,GAAG,CAAC;CAER,OAAO;AACT"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/hooks/useScroll.d.ts
|
|
2
|
+
type ScrollTargetValue = Element | Document | null | undefined;
|
|
3
|
+
export type ScrollTarget = ScrollTargetValue | (() => ScrollTargetValue) | {
|
|
4
|
+
current: ScrollTargetValue;
|
|
5
|
+
};
|
|
6
|
+
//#endregion
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=useScroll.d.mts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
//#region src/hooks/useScroll.ts
|
|
3
|
+
const resolveTarget = (target) => {
|
|
4
|
+
if (typeof target === "function") return target();
|
|
5
|
+
if (target && "current" in target) return target.current;
|
|
6
|
+
return target;
|
|
7
|
+
};
|
|
8
|
+
const readPosition = (element) => {
|
|
9
|
+
const scroller = element instanceof Document ? element.scrollingElement ?? element.documentElement : element;
|
|
10
|
+
return {
|
|
11
|
+
left: scroller.scrollLeft,
|
|
12
|
+
top: scroller.scrollTop
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
const useScroll = (target) => {
|
|
16
|
+
const [position, setPosition] = useState();
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const element = resolveTarget(target);
|
|
19
|
+
if (!element) return;
|
|
20
|
+
const update = () => {
|
|
21
|
+
const next = readPosition(element);
|
|
22
|
+
setPosition((prev) => prev && prev.left === next.left && prev.top === next.top ? prev : next);
|
|
23
|
+
};
|
|
24
|
+
update();
|
|
25
|
+
element.addEventListener("scroll", update, { passive: true });
|
|
26
|
+
return () => element.removeEventListener("scroll", update);
|
|
27
|
+
}, [target]);
|
|
28
|
+
return position;
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { useScroll };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=useScroll.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useScroll.mjs","names":[],"sources":["../../src/hooks/useScroll.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\ntype ScrollTargetValue = Element | Document | null | undefined;\n\nexport type ScrollTarget =\n ScrollTargetValue | (() => ScrollTargetValue) | { current: ScrollTargetValue };\n\nexport interface ScrollPosition {\n left: number;\n top: number;\n}\n\nconst resolveTarget = (target: ScrollTarget): ScrollTargetValue => {\n if (typeof target === 'function') return target();\n if (target && 'current' in target) return target.current;\n return target;\n};\n\nconst readPosition = (element: Element | Document): ScrollPosition => {\n const scroller =\n element instanceof Document ? (element.scrollingElement ?? element.documentElement) : element;\n return { left: scroller.scrollLeft, top: scroller.scrollTop };\n};\n\nexport const useScroll = (target: ScrollTarget): ScrollPosition | undefined => {\n const [position, setPosition] = useState<ScrollPosition>();\n\n useEffect(() => {\n const element = resolveTarget(target);\n if (!element) return;\n const update = () => {\n const next = readPosition(element);\n setPosition((prev) =>\n prev && prev.left === next.left && prev.top === next.top ? prev : next,\n );\n };\n update();\n element.addEventListener('scroll', update, { passive: true });\n return () => element.removeEventListener('scroll', update);\n }, [target]);\n\n return position;\n};\n"],"mappings":";;AAYA,MAAM,iBAAiB,WAA4C;CACjE,IAAI,OAAO,WAAW,YAAY,OAAO,OAAO;CAChD,IAAI,UAAU,aAAa,QAAQ,OAAO,OAAO;CACjD,OAAO;AACT;AAEA,MAAM,gBAAgB,YAAgD;CACpE,MAAM,WACJ,mBAAmB,WAAY,QAAQ,oBAAoB,QAAQ,kBAAmB;CACxF,OAAO;EAAE,MAAM,SAAS;EAAY,KAAK,SAAS;CAAU;AAC9D;AAEA,MAAa,aAAa,WAAqD;CAC7E,MAAM,CAAC,UAAU,eAAe,SAAyB;CAEzD,gBAAgB;EACd,MAAM,UAAU,cAAc,MAAM;EACpC,IAAI,CAAC,SAAS;EACd,MAAM,eAAe;GACnB,MAAM,OAAO,aAAa,OAAO;GACjC,aAAa,SACX,QAAQ,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM,OAAO,IACpE;EACF;EACA,OAAO;EACP,QAAQ,iBAAiB,UAAU,QAAQ,EAAE,SAAS,KAAK,CAAC;EAC5D,aAAa,QAAQ,oBAAoB,UAAU,MAAM;CAC3D,GAAG,CAAC,MAAM,CAAC;CAEX,OAAO;AACT"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useLayoutEffect, useState } from "react";
|
|
2
|
+
//#region src/hooks/useSize.ts
|
|
3
|
+
const useSize = (ref) => {
|
|
4
|
+
const [size, setSize] = useState();
|
|
5
|
+
useLayoutEffect(() => {
|
|
6
|
+
const element = ref.current;
|
|
7
|
+
if (!element) return;
|
|
8
|
+
setSize({
|
|
9
|
+
height: element.clientHeight,
|
|
10
|
+
width: element.clientWidth
|
|
11
|
+
});
|
|
12
|
+
const observer = new ResizeObserver((entries) => {
|
|
13
|
+
for (const { target } of entries) setSize({
|
|
14
|
+
height: target.clientHeight,
|
|
15
|
+
width: target.clientWidth
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
observer.observe(element);
|
|
19
|
+
return () => observer.disconnect();
|
|
20
|
+
}, [ref]);
|
|
21
|
+
return size;
|
|
22
|
+
};
|
|
23
|
+
//#endregion
|
|
24
|
+
export { useSize };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=useSize.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSize.mjs","names":[],"sources":["../../src/hooks/useSize.ts"],"sourcesContent":["import { type RefObject, useLayoutEffect, useState } from 'react';\n\nexport interface ElementSize {\n height: number;\n width: number;\n}\n\nexport const useSize = (ref: RefObject<Element | null>): ElementSize | undefined => {\n const [size, setSize] = useState<ElementSize>();\n\n useLayoutEffect(() => {\n const element = ref.current;\n if (!element) return;\n setSize({ height: element.clientHeight, width: element.clientWidth });\n\n const observer = new ResizeObserver((entries) => {\n for (const { target } of entries) {\n setSize({ height: target.clientHeight, width: target.clientWidth });\n }\n });\n observer.observe(element);\n return () => observer.disconnect();\n }, [ref]);\n\n return size;\n};\n"],"mappings":";;AAOA,MAAa,WAAW,QAA4D;CAClF,MAAM,CAAC,MAAM,WAAW,SAAsB;CAE9C,sBAAsB;EACpB,MAAM,UAAU,IAAI;EACpB,IAAI,CAAC,SAAS;EACd,QAAQ;GAAE,QAAQ,QAAQ;GAAc,OAAO,QAAQ;EAAY,CAAC;EAEpE,MAAM,WAAW,IAAI,gBAAgB,YAAY;GAC/C,KAAK,MAAM,EAAE,YAAY,SACvB,QAAQ;IAAE,QAAQ,OAAO;IAAc,OAAO,OAAO;GAAY,CAAC;EAEtE,CAAC;EACD,SAAS,QAAQ,OAAO;EACxB,aAAa,SAAS,WAAW;CACnC,GAAG,CAAC,GAAG,CAAC;CAER,OAAO;AACT"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { styleProps } from "../../styles/stylex/props.mjs";
|
|
3
|
+
import { useMergeRefs } from "../../utils/mergeRefs.mjs";
|
|
3
4
|
import { ScrollAreaRoot, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewportImpl } from "../../ScrollArea/atoms.mjs";
|
|
4
5
|
import { Children, cloneElement, useCallback, useEffect, useRef } from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { useMergeRefs } from "react-merge-refs";
|
|
7
7
|
import { Virtualizer } from "virtua";
|
|
8
8
|
//#region src/internal/virtual/VirtualScrollArea.tsx
|
|
9
9
|
const styles = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualScrollArea.mjs","names":[],"sources":["../../../src/internal/virtual/VirtualScrollArea.tsx"],"sourcesContent":["'use client';\n\nimport * as stylex from '@stylexjs/stylex';\nimport {\n Children,\n cloneElement,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useEffect,\n useRef,\n} from 'react';\nimport {
|
|
1
|
+
{"version":3,"file":"VirtualScrollArea.mjs","names":[],"sources":["../../../src/internal/virtual/VirtualScrollArea.tsx"],"sourcesContent":["'use client';\n\nimport * as stylex from '@stylexjs/stylex';\nimport {\n Children,\n cloneElement,\n type ReactElement,\n type ReactNode,\n type Ref,\n useCallback,\n useEffect,\n useRef,\n} from 'react';\nimport { Virtualizer, type VirtualizerHandle } from 'virtua';\n\nimport {\n ScrollAreaRoot,\n type ScrollAreaRootProps,\n ScrollAreaScrollbar,\n ScrollAreaThumb,\n ScrollAreaViewportImpl,\n type ScrollAreaViewportProps,\n} from '@/ScrollArea/atoms';\nimport { styleProps } from '@/styles/stylex/props';\nimport { useMergeRefs } from '@/utils/mergeRefs';\n\n// `--lobe-virtual-scroll-inset` is the inline padding of the box the scroll area sits in: the\n// root bleeds out by it so the scrollbar hugs that box's edge, and the viewport pads the rows back.\nconst styles = stylex.create({\n root: {\n marginInline: 'calc(-1 * var(--lobe-virtual-scroll-inset, 0px))',\n display: 'flex',\n flexBasis: '0%',\n flexDirection: 'column',\n flexGrow: 1,\n flexShrink: 1,\n minHeight: 0,\n },\n viewport: {\n paddingInline: 'var(--lobe-virtual-scroll-inset, 0)',\n flexBasis: '0%',\n flexGrow: 1,\n flexShrink: 1,\n height: 'auto',\n minHeight: 0,\n },\n});\n\n// Rows mounted on the very first render, before the viewport is measured, so Base UI's\n// list navigation sees the leading rows (not a pinned footer item) when it focuses on open.\nconst INITIAL_ROW_COUNT = 20;\n\nexport interface VirtualScrollAreaProps extends Omit<ScrollAreaRootProps, 'children'> {\n children: ReactNode;\n itemSize?: number;\n keepMounted?: readonly number[];\n /**\n * Element that owns the scrolling box (e.g. a Base UI `Select.List`); it is rendered\n * through the ScrollArea viewport so its own props and role win.\n */\n viewport?: ReactElement<{ children?: ReactNode; render?: ReactElement }>;\n viewportProps?: ScrollAreaViewportProps;\n virtualizerRef?: Ref<VirtualizerHandle>;\n}\n\nexport const VirtualScrollArea = ({\n children,\n className,\n itemSize,\n keepMounted,\n viewport,\n viewportProps,\n virtualizerRef,\n ...rest\n}: VirtualScrollAreaProps) => {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const mergedViewportRef = useMergeRefs([viewportRef, viewportProps?.ref]);\n\n const list = (\n <Virtualizer\n itemSize={itemSize}\n keepMounted={keepMounted}\n ref={virtualizerRef}\n scrollRef={viewportRef}\n ssrCount={Math.min(INITIAL_ROW_COUNT, Children.count(children))}\n >\n {children}\n </Virtualizer>\n );\n const viewportElement = (\n <ScrollAreaViewportImpl\n tabIndex={-1}\n {...viewportProps}\n ref={mergedViewportRef}\n xstyle={styles.viewport}\n />\n );\n\n return (\n <ScrollAreaRoot\n data-virtual=\"\"\n {...rest}\n className={styleProps(styles.root, className as string).className}\n >\n {cloneElement(viewport ?? viewportElement, {\n children: list,\n ...(viewport && { render: viewportElement }),\n })}\n <ScrollAreaScrollbar>\n <ScrollAreaThumb />\n </ScrollAreaScrollbar>\n </ScrollAreaRoot>\n );\n};\n\nVirtualScrollArea.displayName = 'VirtualScrollArea';\n\n// Base UI scrolls the highlighted item into view after focusing it; while the pointer drives\n// the scroll that would yank the list back, so callers consult `pointerScrollRef` first.\nexport function usePointerScrollGuard() {\n const pointerScrollRef = useRef(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const markPointerScroll = useCallback(() => {\n pointerScrollRef.current = true;\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => {\n pointerScrollRef.current = false;\n }, 120);\n }, []);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n return {\n markPointerScroll,\n pointerScrollRef,\n scrollGuardProps: {\n onPointerDown: markPointerScroll,\n onTouchMove: markPointerScroll,\n onWheel: markPointerScroll,\n },\n };\n}\n"],"mappings":";;;;;;;;AAWA,MAAM,SAAS;CACb,MAAM;EACJ,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,OAAO;CACT;CACA,UAAU;EACR,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,OAAO;CACT;AACF;AAIA,MAAM,oBAAoB;AAgB1B,MAAa,qBAAqB,EAChC,UACA,WACA,UACA,aACA,UACA,eACA,gBACA,GAAG,WACyB;CAC5B,MAAM,cAAc,OAA8B,IAAI;CACtD,MAAM,oBAAoB,aAAa,CAAC,aAAa,eAAe,GAAG,CAAC;CACxE,MAAM,OAAO,oBAAC,aAAD;EAAuB;EAAuB;EAAa,KAAK;EAAgB,WAAW;EAAa,UAAU,KAAK,IAAI,mBAAmB,SAAS,MAAM,QAAQ,CAAC;EAC9K;CACU,CAAA;CACf,MAAM,kBAAkB,oBAAC,wBAAD;EAAwB,UAAU;EAAI,GAAI;EAAe,KAAK;EAAmB,QAAQ,OAAO;CAAW,CAAA;CACnI,OAAO,qBAAC,gBAAD;EAAgB,gBAAa;EAAG,GAAI;EAAM,WAAW,WAAW,OAAO,MAAM,SAAmB,CAAC,CAAC;EAAlG,UAAA,CACF,aAAa,YAAY,iBAAiB;GAC3C,UAAU;GACV,GAAI,YAAY,EACd,QAAQ,gBACV;EACF,CAAC,GACC,oBAAC,qBAAD,EAAA,UACE,oBAAC,iBAAD,CAAkB,CAAA,EACC,CAAA,CACP;;AACpB;AACA,kBAAkB,cAAc;AAIhC,SAAgB,wBAAwB;CACtC,MAAM,mBAAmB,OAAO,KAAK;CACrC,MAAM,aAAa,OAA6C,IAAI;CACpE,MAAM,oBAAoB,kBAAkB;EAC1C,iBAAiB,UAAU;EAC3B,IAAI,WAAW,SAAS,aAAa,WAAW,OAAO;EACvD,WAAW,UAAU,iBAAiB;GACpC,iBAAiB,UAAU;EAC7B,GAAG,GAAG;CACR,GAAG,CAAC,CAAC;CACL,gBAAgB;EACd,aAAa;GACX,IAAI,WAAW,SAAS,aAAa,WAAW,OAAO;EACzD;CACF,GAAG,CAAC,CAAC;CACL,OAAO;EACL;EACA;EACA,kBAAkB;GAChB,eAAe;GACf,aAAa;GACb,SAAS;EACX;CACF;AACF"}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { styleProps } from "../../styles/stylex/props.mjs";
|
|
3
3
|
import FlexBasic_default from "../../Flex/FlexBasic.mjs";
|
|
4
4
|
import ActionIcon from "../../ActionIcon/ActionIcon.mjs";
|
|
5
|
+
import { useSize } from "../../hooks/useSize.mjs";
|
|
5
6
|
import ChatInputAreaInner from "../../chat/ChatInputArea/components/ChatInputAreaInner.mjs";
|
|
6
7
|
import SafeArea from "../SafeArea/SafeArea.mjs";
|
|
7
8
|
import { styles } from "./style.mjs";
|
|
8
9
|
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
9
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
11
|
import { ChevronDown, ChevronUp } from "lucide-react";
|
|
11
|
-
import { useSize } from "ahooks";
|
|
12
12
|
//#region src/mobile/ChatInputArea/ChatInputArea.tsx
|
|
13
13
|
const ChatInputArea = memo(({ ref, className, style, topAddons, textAreaLeftAddons, textAreaRightAddons, bottomAddons, expand = false, setExpand, onSend, onInput, loading, value, safeArea }) => {
|
|
14
14
|
const containerRef = useRef(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatInputArea.mjs","names":["Flexbox"],"sources":["../../../src/mobile/ChatInputArea/ChatInputArea.tsx"],"sourcesContent":["'use client';\n\nimport {
|
|
1
|
+
{"version":3,"file":"ChatInputArea.mjs","names":["Flexbox"],"sources":["../../../src/mobile/ChatInputArea/ChatInputArea.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport {\n type FC,\n memo,\n type PropsWithChildren,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport ChatInputAreaInner from '@/chat/ChatInputArea/components/ChatInputAreaInner';\nimport { Flexbox } from '@/Flex';\nimport { useSize } from '@/hooks/useSize';\nimport SafeArea from '@/mobile/SafeArea';\nimport { styleProps } from '@/styles/stylex/props';\n\nimport { styles } from './style';\nimport { type ChatInputAreaProps } from './type';\n\nconst ChatInputArea = memo<ChatInputAreaProps>(\n ({\n ref,\n className,\n style,\n topAddons,\n textAreaLeftAddons,\n textAreaRightAddons,\n bottomAddons,\n expand = false,\n setExpand,\n onSend,\n onInput,\n loading,\n value,\n safeArea,\n }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const size = useSize(containerRef);\n const [showFullscreen, setShowFullscreen] = useState<boolean>(false);\n const [isFocused, setIsFocused] = useState<boolean>(false);\n\n useEffect(() => {\n if (!size?.height) return;\n setShowFullscreen(size.height > 72);\n }, [size]);\n\n const InnerContainer: FC<\n PropsWithChildren & {\n bottomAddons?: ReactNode;\n textAreaLeftAddons?: ReactNode;\n textAreaRightAddons?: ReactNode;\n topAddons?: ReactNode;\n }\n > = useCallback(\n ({ children, ...r }) =>\n expand ? (\n <Flexbox gap={8} height={'inherit'} paddingInline={8}>\n <Flexbox horizontal gap={8} justify={'flex-end'}>\n {r.textAreaLeftAddons}\n {r.textAreaRightAddons}\n </Flexbox>\n {children}\n {r.topAddons}\n {r.bottomAddons}\n </Flexbox>\n ) : (\n <Flexbox horizontal align={'flex-end'} gap={8} height={'inherit'} paddingInline={8}>\n {r.textAreaLeftAddons}\n {children}\n {r.textAreaRightAddons}\n </Flexbox>\n ),\n [expand, loading],\n );\n\n const showAddons = !expand && !isFocused;\n\n return (\n <Flexbox\n flex={'none'}\n gap={12}\n height={expand ? '100%' : undefined}\n paddingBlock={12}\n width={expand ? '100%' : undefined}\n {...styleProps([styles.container, expand && styles.expand], className, style)}\n >\n {topAddons && <Flexbox style={showAddons ? {} : { display: 'none' }}>{topAddons}</Flexbox>}\n <Flexbox\n height={expand ? '100%' : undefined}\n ref={containerRef}\n style={{ position: 'relative' }}\n width={expand ? '100%' : undefined}\n >\n {showFullscreen && (\n <ActionIcon\n active\n icon={expand ? ChevronDown : ChevronUp}\n id={'sssssss'}\n size={{ blockSize: 24, borderRadius: '50%', size: 14 }}\n style={{ insetInlineEnd: 14, position: 'absolute', ...(expand ? { top: 6 } : {}) }}\n onClick={() => setExpand?.(!expand)}\n />\n )}\n <InnerContainer\n bottomAddons={bottomAddons}\n textAreaLeftAddons={textAreaLeftAddons}\n textAreaRightAddons={textAreaRightAddons}\n topAddons={topAddons}\n >\n <ChatInputAreaInner\n autoSize={expand ? false : { maxRows: 6, minRows: 1 }}\n loading={loading}\n ref={ref}\n style={{ flex: 1, minHeight: 36, paddingBlock: 6 }}\n value={value}\n variant={expand ? 'borderless' : 'filled'}\n onBlur={() => setIsFocused(false)}\n onFocus={() => setIsFocused(true)}\n onInput={onInput}\n onSend={onSend}\n />\n </InnerContainer>\n </Flexbox>\n {bottomAddons && (\n <Flexbox style={showAddons ? {} : { display: 'none' }}>{bottomAddons}</Flexbox>\n )}\n {safeArea && !isFocused && <SafeArea position={'bottom'} />}\n </Flexbox>\n );\n },\n);\n\nChatInputArea.displayName = 'ChatInputArea';\n\nexport default ChatInputArea;\n"],"mappings":";;;;;;;;;;;;AAwBA,MAAM,gBAAgB,MACnB,EACC,KACA,WACA,OACA,WACA,oBACA,qBACA,cACA,SAAS,OACT,WACA,QACA,SACA,SACA,OACA,eACI;CACJ,MAAM,eAAe,OAAuB,IAAI;CAChD,MAAM,OAAO,QAAQ,YAAY;CACjC,MAAM,CAAC,gBAAgB,qBAAqB,SAAkB,KAAK;CACnE,MAAM,CAAC,WAAW,gBAAgB,SAAkB,KAAK;CAEzD,gBAAgB;EACd,IAAI,CAAC,MAAM,QAAQ;EACnB,kBAAkB,KAAK,SAAS,EAAE;CACpC,GAAG,CAAC,IAAI,CAAC;CAET,MAAM,iBAOF,aACD,EAAE,UAAU,GAAG,QACd,SACE,qBAACA,mBAAD;EAAS,KAAK;EAAG,QAAQ;EAAW,eAAe;EAAnD,UAAA;GACE,qBAACA,mBAAD;IAAS,YAAA;IAAW,KAAK;IAAG,SAAS;IAArC,UAAA,CACG,EAAE,oBACF,EAAE,mBACI;;GACR;GACA,EAAE;GACF,EAAE;EACI;CAET,CAAA,IAAA,qBAACA,mBAAD;EAAS,YAAA;EAAW,OAAO;EAAY,KAAK;EAAG,QAAQ;EAAW,eAAe;EAAjF,UAAA;GACG,EAAE;GACF;GACA,EAAE;EACI;CAEb,CAAA,GAAA,CAAC,QAAQ,OAAO,CAClB;CAEA,MAAM,aAAa,CAAC,UAAU,CAAC;CAE/B,OACE,qBAACA,mBAAD;EACE,MAAM;EACN,KAAK;EACL,QAAQ,SAAS,SAAS,KAAA;EAC1B,cAAc;EACd,OAAO,SAAS,SAAS,KAAA;EACzB,GAAI,WAAW,CAAC,OAAO,WAAW,UAAU,OAAO,MAAM,GAAG,WAAW,KAAK;EAN9E,UAAA;GAQG,aAAa,oBAACA,mBAAD;IAAS,OAAO,aAAa,CAAC,IAAI,EAAE,SAAS,OAAO;IAAI,UAAA;GAAmB,CAAA;GACzF,qBAACA,mBAAD;IACE,QAAQ,SAAS,SAAS,KAAA;IAC1B,KAAK;IACL,OAAO,EAAE,UAAU,WAAW;IAC9B,OAAO,SAAS,SAAS,KAAA;IAJ3B,UAAA,CAMG,kBACC,oBAAC,YAAD;KACE,QAAA;KACA,MAAM,SAAS,cAAc;KAC7B,IAAI;KACJ,MAAM;MAAE,WAAW;MAAI,cAAc;MAAO,MAAM;KAAG;KACrD,OAAO;MAAE,gBAAgB;MAAI,UAAU;MAAY,GAAI,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC;KAAG;KACjF,eAAe,YAAY,CAAC,MAAM;IACnC,CAAA,GAEH,oBAAC,gBAAD;KACgB;KACM;KACC;KACV;KAEX,UAAA,oBAAC,oBAAD;MACE,UAAU,SAAS,QAAQ;OAAE,SAAS;OAAG,SAAS;MAAE;MAC3C;MACJ;MACL,OAAO;OAAE,MAAM;OAAG,WAAW;OAAI,cAAc;MAAE;MAC1C;MACP,SAAS,SAAS,eAAe;MACjC,cAAc,aAAa,KAAK;MAChC,eAAe,aAAa,IAAI;MACvB;MACD;KACT,CAAA;IACa,CAAA,CACT;;GACR,gBACC,oBAACA,mBAAD;IAAS,OAAO,aAAa,CAAC,IAAI,EAAE,SAAS,OAAO;IAAI,UAAA;GAAsB,CAAA;GAE/E,YAAY,CAAC,aAAa,oBAAC,UAAD,EAAU,UAAU,SAAW,CAAA;EACnD;;AAEb,CACF;AAEA,cAAc,cAAc"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { styleProps } from "../../styles/stylex/props.mjs";
|
|
3
3
|
import FlexBasic_default from "../../Flex/FlexBasic.mjs";
|
|
4
|
+
import { useControlledState } from "../../hooks/useControlledState.mjs";
|
|
4
5
|
import SafeArea from "../SafeArea/SafeArea.mjs";
|
|
5
6
|
import { styles } from "./style.mjs";
|
|
6
7
|
import { memo } from "react";
|
|
7
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
9
|
import * as stylex from "@stylexjs/stylex";
|
|
9
|
-
import useControlledState from "use-merge-value";
|
|
10
10
|
//#region src/mobile/TabBar/TabBar.tsx
|
|
11
11
|
const TabBar = memo(({ ref, className, safeArea, items, activeKey, defaultActiveKey, onChange, ...rest }) => {
|
|
12
12
|
const [currentActive, setCurrentActive] = useControlledState(defaultActiveKey || items[0].key, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabBar.mjs","names":["
|
|
1
|
+
{"version":3,"file":"TabBar.mjs","names":["Flexbox"],"sources":["../../../src/mobile/TabBar/TabBar.tsx"],"sourcesContent":["'use client';\n\nimport * as stylex from '@stylexjs/stylex';\nimport { memo } from 'react';\n\nimport { Flexbox } from '@/Flex';\nimport { useControlledState } from '@/hooks/useControlledState';\nimport SafeArea from '@/mobile/SafeArea';\nimport { styleProps } from '@/styles/stylex/props';\n\nimport { styles } from './style';\nimport type { TabBarProps } from './type';\n\nconst TabBar = memo<TabBarProps>(\n ({ ref, className, safeArea, items, activeKey, defaultActiveKey, onChange, ...rest }) => {\n const [currentActive, setCurrentActive] = useControlledState<string>(\n defaultActiveKey || items[0].key,\n {\n defaultValue: defaultActiveKey,\n onChange,\n value: activeKey,\n },\n );\n\n return (\n <Flexbox\n as={'footer'}\n flex={'none'}\n ref={ref}\n width={'100vw'}\n {...styleProps(styles.container, className)}\n {...rest}\n >\n <Flexbox\n horizontal\n align={'center'}\n height={48}\n justify={'space-around'}\n {...styleProps(styles.inner, className)}\n >\n {items.map((item) => {\n const active = item.key === currentActive;\n return (\n <Flexbox\n align={'center'}\n gap={4}\n height={48}\n justify={'center'}\n key={item.key}\n width={48}\n {...stylex.props(styles.tab, active && styles.active)}\n onClick={() => {\n setCurrentActive(item.key);\n item?.onClick?.();\n }}\n >\n <Flexbox\n align={'center'}\n height={24}\n justify={'center'}\n width={24}\n {...stylex.props(styles.icon)}\n >\n {typeof item.icon === 'function' ? item.icon(active) : item.icon}\n </Flexbox>\n <div {...stylex.props(styles.title)}>\n {typeof item.title === 'function' ? item.title(active) : item.title}\n </div>\n </Flexbox>\n );\n })}\n </Flexbox>\n {safeArea && <SafeArea position={'bottom'} />}\n </Flexbox>\n );\n },\n);\n\nTabBar.displayName = 'MobileTabBar';\n\nexport default TabBar;\n"],"mappings":";;;;;;;;;;AAUA,MAAM,SAAS,MAAmB,EAChC,KACA,WACA,UACA,OACA,WACA,kBACA,UACA,GAAG,WACC;CACJ,MAAM,CAAC,eAAe,oBAAoB,mBAA2B,oBAAoB,MAAM,EAAE,CAAC,KAAK;EACrG,cAAc;EACd;EACA,OAAO;CACT,CAAC;CACD,OAAO,qBAACA,mBAAD;EAAS,IAAI;EAAU,MAAM;EAAa;EAAK,OAAO;EAAS,GAAI,WAAW,OAAO,WAAW,SAAS;EAAG,GAAI;EAAhH,UAAA,CACD,oBAACA,mBAAD;GAAS,YAAA;GAAW,OAAO;GAAU,QAAQ;GAAI,SAAS;GAAgB,GAAI,WAAW,OAAO,OAAO,SAAS;GAC7G,UAAA,MAAM,KAAI,SAAQ;IACrB,MAAM,SAAS,KAAK,QAAQ;IAC5B,OAAO,qBAACA,mBAAD;KAAS,OAAO;KAAU,KAAK;KAAG,QAAQ;KAAI,SAAS;KAAyB,OAAO;KAAI,GAAI,OAAO,MAAM,OAAO,KAAK,UAAU,OAAO,MAAM;KAAG,eAAe;MACtK,iBAAiB,KAAK,GAAG;MACzB,MAAM,UAAU;KAClB;KAHO,UAAA,CAIC,oBAACA,mBAAD;MAAS,OAAO;MAAU,QAAQ;MAAI,SAAS;MAAU,OAAO;MAAI,GAAI,OAAO,MAAM,OAAO,IAAI;MAC7F,UAAA,OAAO,KAAK,SAAS,aAAa,KAAK,KAAK,MAAM,IAAI,KAAK;KACrD,CAAA,GACT,oBAAC,OAAD;MAAK,GAAI,OAAO,MAAM,OAAO,KAAK;MAC/B,UAAA,OAAO,KAAK,UAAU,aAAa,KAAK,MAAM,MAAM,IAAI,KAAK;KAC3D,CAAA,CACE;IAV8D,GAAA,KAAK,GAUnE;GACjB,CAAC;EACU,CAAA,GACR,YAAY,oBAAC,UAAD,EAAU,UAAU,SAAW,CAAA,CACrC;;AACf,CAAC;AACD,OAAO,cAAc"}
|
package/es/node_modules/.pnpm/@eslint_core@1.2.1/node_modules/@eslint/core/dist/esm/types.d.mts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { JSONSchema4 } from "../../../../../../@types_json-schema@7.0.15/node_modules/@types/json-schema/index.mjs";
|
|
2
|
-
|
|
3
|
-
export { BaseConfig, BinarySourceCode, CallTraversalStep, ConfigObject, ConfigOverride, CustomRuleDefinitionType, CustomRuleTypeDefinitions, DeprecatedInfo, Directive, DirectiveType, EcmaVersion, EnvironmentConfig, ExternalSpecifier, File, FileError, FileProblem, GlobalAccess, GlobalsConfig, HasRules, JavaScriptParserOptionsConfig, JavaScriptSourceType, Language, LanguageContext, LanguageOptions, LanguageTypeOptions, LegacyConfigObject, LintMessage, LintSuggestion, LinterOptionsConfig, MessagePlaceholderData, NotOkParseResult, ObjectMetaProperties, OkParseResult, ParseResult, Plugin, Position, PositionWithOffset, Processor, ProcessorFile, ReplacedByInfo, RuleConfig, RuleContext, RuleContextTypeOptions, RuleDefinition, RuleDefinitionTypeOptions, RuleFixType, RuleFixer, RuleTextEdit, RuleTextEditor, RuleType, RuleVisitor, RulesConfig, RulesMeta, RulesMetaDocs, SettingsConfig, Severity, SeverityLevel, SeverityName, SourceCode, SourceCodeBaseTypeOptions, SourceLocation, SourceLocationWithOffset, SourceRange, SuggestedEdit, SuggestedEditBase, SuggestionMessage, TextSourceCode, TraversalStep, ViolationLocation, ViolationMessage, ViolationReport, ViolationReportBase, VisitTraversalStep };
|
|
4
|
-
}
|
|
2
|
+
//#region node_modules/.pnpm/@eslint+core@1.2.1/node_modules/@eslint/core/dist/esm/types.d.ts
|
|
5
3
|
/**
|
|
6
4
|
* Represents an error inside of a file.
|
|
7
5
|
*/
|
|
@@ -27,13 +25,6 @@ export interface SourceLocation {
|
|
|
27
25
|
start: Position;
|
|
28
26
|
end: Position;
|
|
29
27
|
}
|
|
30
|
-
/**
|
|
31
|
-
* Represents the start and end coordinates of a node inside the source with an offset.
|
|
32
|
-
*/
|
|
33
|
-
export interface SourceLocationWithOffset {
|
|
34
|
-
start: PositionWithOffset;
|
|
35
|
-
end: PositionWithOffset;
|
|
36
|
-
}
|
|
37
28
|
/**
|
|
38
29
|
* Represents a location coordinate inside the source. ESLint-style formats
|
|
39
30
|
* have just `line` and `column` while others may have `offset` as well.
|
|
@@ -42,12 +33,6 @@ export interface Position {
|
|
|
42
33
|
line: number;
|
|
43
34
|
column: number;
|
|
44
35
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Represents a location coordinate inside the source with an offset.
|
|
47
|
-
*/
|
|
48
|
-
export interface PositionWithOffset extends Position {
|
|
49
|
-
offset: number;
|
|
50
|
-
}
|
|
51
36
|
/**
|
|
52
37
|
* Represents a range of characters in the source.
|
|
53
38
|
*/
|
|
@@ -472,35 +457,6 @@ export interface RuleDefinition<Options extends RuleDefinitionTypeOptions = Rule
|
|
|
472
457
|
MessageIds: Options["MessageIds"];
|
|
473
458
|
}>): Options["Visitor"];
|
|
474
459
|
}
|
|
475
|
-
/**
|
|
476
|
-
* Defaults for non-language-related `RuleDefinition` options.
|
|
477
|
-
* @deprecated Use the same type from `@eslint/plugin-kit` instead.
|
|
478
|
-
*/
|
|
479
|
-
export interface CustomRuleTypeDefinitions {
|
|
480
|
-
RuleOptions: unknown[];
|
|
481
|
-
MessageIds: string;
|
|
482
|
-
ExtRuleDocs: Record<string, unknown>;
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* A helper type to define language specific specializations of the `RuleDefinition` type.
|
|
486
|
-
* @deprecated Use the same type from `@eslint/plugin-kit` instead.
|
|
487
|
-
*
|
|
488
|
-
* @example
|
|
489
|
-
* ```ts
|
|
490
|
-
* type YourRuleDefinition<
|
|
491
|
-
* Options extends Partial<CustomRuleTypeDefinitions> = {},
|
|
492
|
-
* > = CustomRuleDefinitionType<
|
|
493
|
-
* {
|
|
494
|
-
* LangOptions: YourLanguageOptions;
|
|
495
|
-
* Code: YourSourceCode;
|
|
496
|
-
* Visitor: YourRuleVisitor;
|
|
497
|
-
* Node: YourNode;
|
|
498
|
-
* },
|
|
499
|
-
* Options
|
|
500
|
-
* >;
|
|
501
|
-
* ```
|
|
502
|
-
*/
|
|
503
|
-
export type CustomRuleDefinitionType<LanguageSpecificOptions extends Omit<RuleDefinitionTypeOptions, keyof CustomRuleTypeDefinitions>, Options extends Partial<CustomRuleTypeDefinitions>> = RuleDefinition<LanguageSpecificOptions & Required<Options & Omit<CustomRuleTypeDefinitions, keyof Options>>>;
|
|
504
460
|
/**
|
|
505
461
|
* The human readable severity level used in a configuration.
|
|
506
462
|
*/
|
|
@@ -1157,5 +1113,5 @@ export interface Directive {
|
|
|
1157
1113
|
justification?: string;
|
|
1158
1114
|
}
|
|
1159
1115
|
//#endregion
|
|
1160
|
-
export {
|
|
1116
|
+
export {};
|
|
1161
1117
|
//# sourceMappingURL=types.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RuleVisitor as RuleVisitor$1
|
|
1
|
+
import { RuleVisitor as RuleVisitor$1 } from "../../../../../../@eslint_core@1.2.1/node_modules/@eslint/core/dist/esm/types.mjs";
|
|
2
2
|
import { CustomRuleVisitorWithExit as CustomRuleVisitorWithExit$1 } from "./types.mjs";
|
|
3
3
|
//#region node_modules/.pnpm/@eslint+plugin-kit@0.7.3/node_modules/@eslint/plugin-kit/dist/cjs/index.d.cts
|
|
4
4
|
export type RuleVisitor = RuleVisitor$1;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
export { ArrayExpression, ArrayPattern, ArrowFunctionExpression, AssignmentExpression, AssignmentOperator, AssignmentPattern, AssignmentProperty, AwaitExpression, BaseCallExpression, BaseClass, BaseDeclaration, BaseExpression, BaseForXStatement, BaseFunction, BaseModuleDeclaration, BaseModuleSpecifier, BaseNode, BaseNodeWithoutComments, BasePattern, BaseStatement, BigIntLiteral, BinaryExpression, BinaryOperator, BlockStatement, BreakStatement, CallExpression, CatchClause, ChainElement, ChainExpression, Class, ClassBody, ClassDeclaration, ClassExpression, Comment, ConditionalExpression, ContinueStatement, DebuggerStatement, Declaration, Directive, DoWhileStatement, EmptyStatement, ExportAllDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, ExportSpecifier, Expression, ExpressionMap, ExpressionStatement, ForInStatement, ForOfStatement, ForStatement, Function, FunctionDeclaration, FunctionExpression, Identifier, IfStatement, ImportAttribute, ImportDeclaration, ImportDefaultSpecifier, ImportExpression, ImportNamespaceSpecifier, ImportSpecifier, LabeledStatement, Literal, LogicalExpression, LogicalOperator, MaybeNamedClassDeclaration, MaybeNamedFunctionDeclaration, MemberExpression, MetaProperty, MethodDefinition, ModuleDeclaration, ModuleSpecifier, NewExpression, Node, NodeMap, ObjectExpression, ObjectPattern, Pattern, Position, PrivateIdentifier, Program, Property, PropertyDefinition, RegExpLiteral, RestElement, ReturnStatement, SequenceExpression, SimpleCallExpression, SimpleLiteral, SourceLocation, SpreadElement, Statement, StaticBlock, Super, SwitchCase, SwitchStatement, TaggedTemplateExpression, TemplateElement, TemplateLiteral, ThisExpression, ThrowStatement, TryStatement, UnaryExpression, UnaryOperator, UpdateExpression, UpdateOperator, VariableDeclaration, VariableDeclarator, WhileStatement, WithStatement, YieldExpression };
|
|
3
|
-
}
|
|
1
|
+
//#region node_modules/.pnpm/@types+estree@1.0.9/node_modules/@types/estree/index.d.ts
|
|
4
2
|
// This definition file follows a somewhat unusual format. ESTree allows
|
|
5
3
|
// runtime type checks based on the `type` parameter. In order to explain this
|
|
6
4
|
// to typescript we want to use discriminated union types:
|
|
@@ -526,5 +524,4 @@ export interface AwaitExpression extends BaseExpression {
|
|
|
526
524
|
argument: Expression;
|
|
527
525
|
}
|
|
528
526
|
//#endregion
|
|
529
|
-
export { index_d_exports };
|
|
530
527
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrowFunctionExpression, AssignmentExpression, BaseNode, CatchClause, ClassDeclaration, ClassExpression, Comment, Expression, ForInStatement, ForOfStatement, FunctionDeclaration, FunctionExpression, Identifier, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, Node as Node$1, Position, Program, SourceLocation as SourceLocation$1, VariableDeclaration, VariableDeclarator
|
|
1
|
+
import { ArrowFunctionExpression, AssignmentExpression, BaseNode, CatchClause, ClassDeclaration, ClassExpression, Comment, Expression, ForInStatement, ForOfStatement, FunctionDeclaration, FunctionExpression, Identifier, ImportDeclaration, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, Node as Node$1, Position, Program, SourceLocation as SourceLocation$1, VariableDeclaration, VariableDeclarator } from "../../../../../@types_estree@1.0.9/node_modules/@types/estree/index.mjs";
|
|
2
2
|
import { BaseConfig, ConfigObject, ConfigOverride, DeprecatedInfo, EcmaVersion as EcmaVersion$1, EnvironmentConfig, GlobalAccess, GlobalsConfig, HasRules, JavaScriptSourceType, LanguageOptions, LegacyConfigObject, LintMessage as LintMessage$1, LintSuggestion, LinterOptionsConfig, ObjectMetaProperties, Plugin as Plugin$1, Processor, ProcessorFile as ProcessorFile$1, RuleConfig, RuleContext as RuleContext$1, RuleDefinition, RuleFixer, RuleTextEdit, RuleTextEditor, RulesConfig, RulesMeta, Severity, SeverityLevel, SeverityName, SourceRange, SuggestedEdit, SuggestedEditBase, SuggestionMessage, TextSourceCode, TraversalStep, ViolationLocation, ViolationMessage, ViolationReport, ViolationReportBase } from "../../../../../@eslint_core@1.2.1/node_modules/@eslint/core/dist/esm/types.mjs";
|
|
3
3
|
import { CustomRuleVisitorWithExit } from "../../../../../@eslint_plugin-kit@0.7.3/node_modules/@eslint/plugin-kit/dist/cjs/index.mjs";
|
|
4
4
|
//#region node_modules/.pnpm/eslint@10.12.0_jiti@2.6.1_supports-color@10.2.2/node_modules/eslint/lib/types/index.d.ts
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import gray from "../../../color/colors/gray.mjs";
|
|
2
2
|
import { neutralColorScales } from "../../../color/neutrals/index.mjs";
|
|
3
|
+
import { mixColors, parseRgb } from "../../../utils/colorMath.mjs";
|
|
3
4
|
import { generateColorNeutralPalette } from "../generateColorPalette.mjs";
|
|
4
|
-
import { mix, parseToRgb } from "polished";
|
|
5
5
|
//#region src/styles/theme/token/neutral.ts
|
|
6
6
|
const isChannel = (value) => value >= 0 && value <= 255;
|
|
7
7
|
const getAlphaColor = (front, back) => {
|
|
8
|
-
const f =
|
|
9
|
-
if (
|
|
10
|
-
const b =
|
|
8
|
+
const f = parseRgb(front);
|
|
9
|
+
if (f.alpha !== void 0) return front;
|
|
10
|
+
const b = parseRgb(back);
|
|
11
11
|
for (let alpha = .01; alpha <= 1; alpha += .01) {
|
|
12
12
|
const r = Math.round((f.red - b.red * (1 - alpha)) / alpha);
|
|
13
13
|
const g = Math.round((f.green - b.green * (1 - alpha)) / alpha);
|
|
@@ -28,7 +28,7 @@ const createNeutralToken = (appearance, neutralColor, status) => {
|
|
|
28
28
|
return {
|
|
29
29
|
...token,
|
|
30
30
|
colorBgContainerDisabled: token.colorFillTertiary,
|
|
31
|
-
colorBgContainerSecondary:
|
|
31
|
+
colorBgContainerSecondary: mixColors(.5, token.colorBgLayout, token.colorBgContainer),
|
|
32
32
|
colorBgTextActive: token.colorFill,
|
|
33
33
|
colorBgTextHover: token.colorFillSecondary,
|
|
34
34
|
colorBorderBg: token.colorBgContainer,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neutral.mjs","names":[],"sources":["../../../../src/styles/theme/token/neutral.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"neutral.mjs","names":[],"sources":["../../../../src/styles/theme/token/neutral.ts"],"sourcesContent":["import { gray } from '@/color/colors';\nimport { neutralColorScales } from '@/color/neutrals';\nimport { mixColors, parseRgb } from '@/utils/colorMath';\n\nimport type { NeutralColors } from '../../customTheme';\nimport { generateColorNeutralPalette } from '../generateColorPalette';\n\nconst isChannel = (value: number) => value >= 0 && value <= 255;\n\n// port of antd's getAlphaColor: the most transparent rgba that renders `front` over `back`\nconst getAlphaColor = (front: string, back: string) => {\n const f = parseRgb(front);\n if (f.alpha !== undefined) return front;\n const b = parseRgb(back);\n\n for (let alpha = 0.01; alpha <= 1; alpha += 0.01) {\n const r = Math.round((f.red - b.red * (1 - alpha)) / alpha);\n const g = Math.round((f.green - b.green * (1 - alpha)) / alpha);\n const bl = Math.round((f.blue - b.blue * (1 - alpha)) / alpha);\n if (isChannel(r) && isChannel(g) && isChannel(bl)) {\n const a = Math.round(alpha * 100) / 100;\n return a === 1 ? `rgb(${r},${g},${bl})` : `rgba(${r},${g},${bl},${a})`;\n }\n }\n\n return `rgb(${f.red},${f.green},${f.blue})`;\n};\n\nexport const createNeutralToken = (\n appearance: 'light' | 'dark',\n neutralColor: NeutralColors | undefined,\n status: { colorErrorBg: string; colorWarningBg: string },\n) => {\n const scale = (neutralColor && neutralColorScales[neutralColor]) || gray;\n const token = generateColorNeutralPalette({ appearance, scale });\n\n return {\n ...token,\n colorBgContainerDisabled: token.colorFillTertiary,\n colorBgContainerSecondary: mixColors(0.5, token.colorBgLayout, token.colorBgContainer),\n colorBgTextActive: token.colorFill,\n colorBgTextHover: token.colorFillSecondary,\n colorBorderBg: token.colorBgContainer,\n colorErrorOutline: getAlphaColor(status.colorErrorBg, token.colorBgContainer),\n colorFillAlter: token.colorFillQuaternary,\n colorFillContent: token.colorFillSecondary,\n colorFillContentHover: token.colorFill,\n colorIcon: token.colorTextTertiary,\n colorIconHover: token.colorText,\n colorSplit: getAlphaColor(token.colorBorderSecondary, token.colorBgContainer),\n colorTextDescription: token.colorTextTertiary,\n colorTextDisabled: token.colorTextQuaternary,\n colorTextHeading: token.colorText,\n colorTextLabel: token.colorTextSecondary,\n colorTextPlaceholder: token.colorTextQuaternary,\n colorWarningOutline: getAlphaColor(status.colorWarningBg, token.colorBgContainer),\n controlItemBgActiveDisabled: token.colorFill,\n controlItemBgHover: token.colorFillTertiary,\n controlTmpOutline: token.colorFillQuaternary,\n };\n};\n"],"mappings":";;;;;AAOA,MAAM,aAAa,UAAkB,SAAS,KAAK,SAAS;AAG5D,MAAM,iBAAiB,OAAe,SAAiB;CACrD,MAAM,IAAI,SAAS,KAAK;CACxB,IAAI,EAAE,UAAU,KAAA,GAAW,OAAO;CAClC,MAAM,IAAI,SAAS,IAAI;CAEvB,KAAK,IAAI,QAAQ,KAAM,SAAS,GAAG,SAAS,KAAM;EAChD,MAAM,IAAI,KAAK,OAAO,EAAE,MAAM,EAAE,OAAO,IAAI,UAAU,KAAK;EAC1D,MAAM,IAAI,KAAK,OAAO,EAAE,QAAQ,EAAE,SAAS,IAAI,UAAU,KAAK;EAC9D,MAAM,KAAK,KAAK,OAAO,EAAE,OAAO,EAAE,QAAQ,IAAI,UAAU,KAAK;EAC7D,IAAI,UAAU,CAAC,KAAK,UAAU,CAAC,KAAK,UAAU,EAAE,GAAG;GACjD,MAAM,IAAI,KAAK,MAAM,QAAQ,GAAG,IAAI;GACpC,OAAO,MAAM,IAAI,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,KAAK,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,EAAE;EACtE;CACF;CAEA,OAAO,OAAO,EAAE,IAAI,GAAG,EAAE,MAAM,GAAG,EAAE,KAAK;AAC3C;AAEA,MAAa,sBACX,YACA,cACA,WACG;CACH,MAAM,QAAS,gBAAgB,mBAAmB,iBAAkB;CACpE,MAAM,QAAQ,4BAA4B;EAAE;EAAY;CAAM,CAAC;CAE/D,OAAO;EACL,GAAG;EACH,0BAA0B,MAAM;EAChC,2BAA2B,UAAU,IAAK,MAAM,eAAe,MAAM,gBAAgB;EACrF,mBAAmB,MAAM;EACzB,kBAAkB,MAAM;EACxB,eAAe,MAAM;EACrB,mBAAmB,cAAc,OAAO,cAAc,MAAM,gBAAgB;EAC5E,gBAAgB,MAAM;EACtB,kBAAkB,MAAM;EACxB,uBAAuB,MAAM;EAC7B,WAAW,MAAM;EACjB,gBAAgB,MAAM;EACtB,YAAY,cAAc,MAAM,sBAAsB,MAAM,gBAAgB;EAC5E,sBAAsB,MAAM;EAC5B,mBAAmB,MAAM;EACzB,kBAAkB,MAAM;EACxB,gBAAgB,MAAM;EACtB,sBAAsB,MAAM;EAC5B,qBAAqB,cAAc,OAAO,gBAAgB,MAAM,gBAAgB;EAChF,6BAA6B,MAAM;EACnC,oBAAoB,MAAM;EAC1B,mBAAmB,MAAM;CAC3B;AACF"}
|