@yoka-ui/ui 1.1.1 → 1.1.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.
Files changed (84) hide show
  1. package/@Docs-yoka/exports.generated.md +53 -4
  2. package/dist/es/assets/image/skills.zip +0 -0
  3. package/dist/es/business/AiChat/index.js +15 -13
  4. package/dist/es/business/AiChat/index.js.map +2 -2
  5. package/dist/es/business/AiChat/useAiChat.js +41 -24
  6. package/dist/es/business/AiChat/useAiChat.js.map +2 -2
  7. package/dist/es/business/Editor/index.d.ts +2 -2
  8. package/dist/es/business/Editor/index.js.map +2 -2
  9. package/dist/es/business/Empty/index.d.ts +1 -1
  10. package/dist/es/business/Empty/index.js.map +1 -1
  11. package/dist/es/business/ModCommonFilter/index.d.ts +1 -0
  12. package/dist/es/business/ModCommonFilter/index.js.map +2 -2
  13. package/dist/es/business/YkLoginModule/index.d.ts +1 -0
  14. package/dist/es/business/YkLoginModule/index.js.map +2 -2
  15. package/dist/es/business/YkPorjectSelect/index.d.ts +3 -3
  16. package/dist/es/business/YkPorjectSelect/index.js +37 -51
  17. package/dist/es/business/YkPorjectSelect/index.js.map +2 -2
  18. package/dist/es/business/YkSqlEdit/index.d.ts +1 -0
  19. package/dist/es/business/YkSqlEdit/index.js.map +2 -2
  20. package/dist/es/components/Clock/index.d.ts +2 -2
  21. package/dist/es/components/Clock/index.js.map +2 -2
  22. package/dist/es/components/DebounceInput/index.d.ts +2 -2
  23. package/dist/es/components/DebounceInput/index.js.map +2 -2
  24. package/dist/es/components/MultipleSelect/index.d.ts +2 -2
  25. package/dist/es/components/MultipleSelect/index.js.map +2 -2
  26. package/dist/es/components/RefreshButton/index.d.ts +2 -2
  27. package/dist/es/components/RefreshButton/index.js.map +2 -2
  28. package/dist/es/components/SearchWithHistory/index.d.ts +1 -1
  29. package/dist/es/components/SearchWithHistory/index.js.map +1 -1
  30. package/dist/es/components/TextWithInput/index.d.ts +2 -5
  31. package/dist/es/components/TextWithInput/index.js.map +2 -2
  32. package/dist/es/components/TextWithToolTip/index.d.ts +2 -2
  33. package/dist/es/components/TextWithToolTip/index.js.map +2 -2
  34. package/dist/es/components/TreeTransfer/index.d.ts +1 -0
  35. package/dist/es/components/TreeTransfer/index.js.map +2 -2
  36. package/dist/es/index.d.ts +29 -0
  37. package/dist/es/index.js.map +2 -2
  38. package/dist/es/index.less +1 -0
  39. package/dist/es/layout/YkContainer/index.d.ts +24 -14
  40. package/dist/es/layout/YkContainer/index.js +7 -41
  41. package/dist/es/layout/YkContainer/index.js.map +2 -2
  42. package/dist/es/layout/YkContainer/index.module.less +73 -0
  43. package/dist/lib/assets/image/skills.zip +0 -0
  44. package/dist/lib/business/AiChat/index.js +15 -13
  45. package/dist/lib/business/AiChat/index.js.map +2 -2
  46. package/dist/lib/business/AiChat/useAiChat.js +40 -22
  47. package/dist/lib/business/AiChat/useAiChat.js.map +2 -2
  48. package/dist/lib/business/Editor/index.d.ts +2 -2
  49. package/dist/lib/business/Editor/index.js.map +2 -2
  50. package/dist/lib/business/Empty/index.d.ts +1 -1
  51. package/dist/lib/business/Empty/index.js.map +1 -1
  52. package/dist/lib/business/ModCommonFilter/index.d.ts +1 -0
  53. package/dist/lib/business/ModCommonFilter/index.js.map +2 -2
  54. package/dist/lib/business/YkLoginModule/index.d.ts +1 -0
  55. package/dist/lib/business/YkLoginModule/index.js.map +2 -2
  56. package/dist/lib/business/YkPorjectSelect/index.d.ts +3 -3
  57. package/dist/lib/business/YkPorjectSelect/index.js +33 -27
  58. package/dist/lib/business/YkPorjectSelect/index.js.map +2 -2
  59. package/dist/lib/business/YkSqlEdit/index.d.ts +1 -0
  60. package/dist/lib/business/YkSqlEdit/index.js.map +2 -2
  61. package/dist/lib/components/Clock/index.d.ts +2 -2
  62. package/dist/lib/components/Clock/index.js.map +2 -2
  63. package/dist/lib/components/DebounceInput/index.d.ts +2 -2
  64. package/dist/lib/components/DebounceInput/index.js.map +2 -2
  65. package/dist/lib/components/MultipleSelect/index.d.ts +2 -2
  66. package/dist/lib/components/MultipleSelect/index.js.map +2 -2
  67. package/dist/lib/components/RefreshButton/index.d.ts +2 -2
  68. package/dist/lib/components/RefreshButton/index.js.map +2 -2
  69. package/dist/lib/components/SearchWithHistory/index.d.ts +1 -1
  70. package/dist/lib/components/SearchWithHistory/index.js.map +1 -1
  71. package/dist/lib/components/TextWithInput/index.d.ts +2 -5
  72. package/dist/lib/components/TextWithInput/index.js.map +2 -2
  73. package/dist/lib/components/TextWithToolTip/index.d.ts +2 -2
  74. package/dist/lib/components/TextWithToolTip/index.js.map +2 -2
  75. package/dist/lib/components/TreeTransfer/index.d.ts +1 -0
  76. package/dist/lib/components/TreeTransfer/index.js.map +2 -2
  77. package/dist/lib/index.d.ts +29 -0
  78. package/dist/lib/index.js.map +2 -2
  79. package/dist/lib/index.less +1 -0
  80. package/dist/lib/layout/YkContainer/index.d.ts +24 -14
  81. package/dist/lib/layout/YkContainer/index.js +6 -39
  82. package/dist/lib/layout/YkContainer/index.js.map +3 -3
  83. package/dist/lib/layout/YkContainer/index.module.less +73 -0
  84. package/package.json +6 -5
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/business/Editor/index.tsx"],
4
- "sourcesContent": ["import type { IDomEditor, IEditorConfig } from '@wangeditor/editor';\nimport { Editor } from '@wangeditor/editor-for-react';\nimport '@wangeditor/editor/dist/css/style.css'; // 引入 css\nimport React, { type FC, useEffect, useState } from 'react';\nimport './index.less';\n\ntype PageTypes = {\n value: string;\n onChange?: (value: string) => void;\n style?: React.CSSProperties;\n readOnly?: boolean;\n};\n\nconst NoteEditor: FC<PageTypes> = ({ value, onChange, style, readOnly = false }) => {\n // editor 实例\n const [editor, setEditor] = useState<IDomEditor | null>(null);\n\n // 编辑器配置\n const editorConfig: Partial<IEditorConfig> = {\n placeholder: '请输入内容...',\n readOnly: readOnly,\n // 配置 hoverbar 菜单项\n hoverbarKeys: {\n text: {\n menuKeys: [\n 'headerSelect', // N级标题\n 'justifyLeft', // 左对齐按钮\n 'justifyCenter', // 居中按钮\n 'justifyRight', // 右对齐按钮\n 'bulletedList', // 无序列表\n 'numberedList', // 有序列表\n '|', // 分隔符\n 'color', // 字色\n 'bgColor', // 字背景\n 'bold', // 加粗按钮\n 'through', // 删除按钮(删除线)\n 'italic', // 斜体按钮\n 'underline', // 下划线按钮\n ],\n },\n },\n };\n\n // 及时销毁 editor ,重要!\n useEffect(() => {\n return () => {\n if (editor === null) return;\n editor.destroy();\n setEditor(null);\n };\n }, [editor]);\n\n return (\n <Editor\n defaultConfig={editorConfig}\n value={value}\n onCreated={setEditor}\n onChange={(editor) => onChange?.(editor.getHtml())}\n mode='default'\n style={{ ...style }}\n />\n );\n};\n\nexport default NoteEditor;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AACA,SAAS,cAAc;AACvB,OAAO;AACP,OAAO,SAAkB,WAAW,gBAAgB;AACpD,OAAO;AASP,IAAM,aAA4B,CAAC,EAAE,OAAO,UAAU,OAAO,WAAW,MAAM,MAAM;AAElF,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA4B,IAAI;AAG5D,QAAM,eAAuC;AAAA,IAC3C,aAAa;AAAA,IACb;AAAA;AAAA,IAEA,cAAc;AAAA,MACZ,MAAM;AAAA,QACJ,UAAU;AAAA,UACR;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,WAAW;AAAM;AACrB,aAAO,QAAQ;AACf,gBAAU,IAAI;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAe;AAAA,MACf;AAAA,MACA,WAAW;AAAA,MACX,UAAU,CAACA,YAAW,qCAAWA,QAAO,QAAQ;AAAA,MAChD,MAAK;AAAA,MACL,OAAO,mBAAK;AAAA;AAAA,EACd;AAEJ;AAEA,IAAO,iBAAQ;",
4
+ "sourcesContent": ["import type { IDomEditor, IEditorConfig } from '@wangeditor/editor';\nimport { Editor } from '@wangeditor/editor-for-react';\nimport '@wangeditor/editor/dist/css/style.css'; // 引入 css\nimport React, { type FC, useEffect, useState } from 'react';\nimport './index.less';\n\nexport type EditorProps = {\n value: string;\n onChange?: (value: string) => void;\n style?: React.CSSProperties;\n readOnly?: boolean;\n};\n\nconst NoteEditor: FC<EditorProps> = ({ value, onChange, style, readOnly = false }) => {\n // editor 实例\n const [editor, setEditor] = useState<IDomEditor | null>(null);\n\n // 编辑器配置\n const editorConfig: Partial<IEditorConfig> = {\n placeholder: '请输入内容...',\n readOnly: readOnly,\n // 配置 hoverbar 菜单项\n hoverbarKeys: {\n text: {\n menuKeys: [\n 'headerSelect', // N级标题\n 'justifyLeft', // 左对齐按钮\n 'justifyCenter', // 居中按钮\n 'justifyRight', // 右对齐按钮\n 'bulletedList', // 无序列表\n 'numberedList', // 有序列表\n '|', // 分隔符\n 'color', // 字色\n 'bgColor', // 字背景\n 'bold', // 加粗按钮\n 'through', // 删除按钮(删除线)\n 'italic', // 斜体按钮\n 'underline', // 下划线按钮\n ],\n },\n },\n };\n\n // 及时销毁 editor ,重要!\n useEffect(() => {\n return () => {\n if (editor === null) return;\n editor.destroy();\n setEditor(null);\n };\n }, [editor]);\n\n return (\n <Editor\n defaultConfig={editorConfig}\n value={value}\n onCreated={setEditor}\n onChange={(editor) => onChange?.(editor.getHtml())}\n mode='default'\n style={{ ...style }}\n />\n );\n};\n\nexport default NoteEditor;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AACA,SAAS,cAAc;AACvB,OAAO;AACP,OAAO,SAAkB,WAAW,gBAAgB;AACpD,OAAO;AASP,IAAM,aAA8B,CAAC,EAAE,OAAO,UAAU,OAAO,WAAW,MAAM,MAAM;AAEpF,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA4B,IAAI;AAG5D,QAAM,eAAuC;AAAA,IAC3C,aAAa;AAAA,IACb;AAAA;AAAA,IAEA,cAAc;AAAA,MACZ,MAAM;AAAA,QACJ,UAAU;AAAA,UACR;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,WAAW;AAAM;AACrB,aAAO,QAAQ;AACf,gBAAU,IAAI;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAe;AAAA,MACf;AAAA,MACA,WAAW;AAAA,MACX,UAAU,CAACA,YAAW,qCAAWA,QAAO,QAAQ;AAAA,MAChD,MAAK;AAAA,MACL,OAAO,mBAAK;AAAA;AAAA,EACd;AAEJ;AAEA,IAAO,iBAAQ;",
6
6
  "names": ["editor"]
7
7
  }
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  /**
3
3
  * 空状态占位组件的 Props(ref 由 forwardRef 注入,无需在 props 中声明)
4
4
  */
5
- type EmptyProps = {
5
+ export type EmptyProps = {
6
6
  /** 空状态插图,不传则使用默认 empty.png */
7
7
  image?: React.ReactNode | string;
8
8
  /** 描述文案或自定义节点,默认「暂无数据」 */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/business/Empty/index.tsx"],
4
- "sourcesContent": ["import { Empty, Flex } from 'antd';\nimport type { ForwardedRef } from 'react';\nimport React from 'react';\nimport EmptyImg from './empty.png';\n\n/**\n * 空状态占位组件的 Props(ref 由 forwardRef 注入,无需在 props 中声明)\n */\ntype EmptyProps = {\n /** 空状态插图,不传则使用默认 empty.png */\n image?: React.ReactNode | string;\n /** 描述文案或自定义节点,默认「暂无数据」 */\n description?: string | React.ReactNode;\n /** 图片容器样式,会与默认宽高合并 */\n imageStyle?: React.CSSProperties;\n /** 根节点 Flex 的样式 */\n style?: React.CSSProperties;\n};\n\n/** 描述文字统一样式 */\nconst descriptionStyle: React.CSSProperties = {\n color: '#999',\n fontSize: 14,\n height: 20,\n lineHeight: '20px',\n};\n\n/**\n * 空状态占位:居中展示默认图 + 描述,支持自定义图片与文案,支持 ref 透传。\n */\nconst ForwardedEmptyPlaceholder = React.forwardRef(\n ({ image, description, imageStyle = {}, style = {} }: EmptyProps, ref: ForwardedRef<HTMLDivElement>) => {\n return (\n <Flex ref={ref} style={{ padding: '80px 0', ...style }} align='center' justify='center'>\n <Empty\n image={image || EmptyImg}\n styles={{\n image: {\n height: 60,\n width: 150,\n display: 'inline-block',\n ...imageStyle,\n },\n }}\n description={\n description == null || description === '' ? (\n <span style={descriptionStyle}>暂无数据</span>\n ) : typeof description === 'string' ? (\n <span style={descriptionStyle}>{description}</span>\n ) : (\n description\n )\n }\n />\n </Flex>\n );\n },\n);\n\nForwardedEmptyPlaceholder.displayName = 'Empty';\n\nexport default ForwardedEmptyPlaceholder;\n"],
4
+ "sourcesContent": ["import { Empty, Flex } from 'antd';\nimport type { ForwardedRef } from 'react';\nimport React from 'react';\nimport EmptyImg from './empty.png';\n\n/**\n * 空状态占位组件的 Props(ref 由 forwardRef 注入,无需在 props 中声明)\n */\nexport type EmptyProps = {\n /** 空状态插图,不传则使用默认 empty.png */\n image?: React.ReactNode | string;\n /** 描述文案或自定义节点,默认「暂无数据」 */\n description?: string | React.ReactNode;\n /** 图片容器样式,会与默认宽高合并 */\n imageStyle?: React.CSSProperties;\n /** 根节点 Flex 的样式 */\n style?: React.CSSProperties;\n};\n\n/** 描述文字统一样式 */\nconst descriptionStyle: React.CSSProperties = {\n color: '#999',\n fontSize: 14,\n height: 20,\n lineHeight: '20px',\n};\n\n/**\n * 空状态占位:居中展示默认图 + 描述,支持自定义图片与文案,支持 ref 透传。\n */\nconst ForwardedEmptyPlaceholder = React.forwardRef(\n ({ image, description, imageStyle = {}, style = {} }: EmptyProps, ref: ForwardedRef<HTMLDivElement>) => {\n return (\n <Flex ref={ref} style={{ padding: '80px 0', ...style }} align='center' justify='center'>\n <Empty\n image={image || EmptyImg}\n styles={{\n image: {\n height: 60,\n width: 150,\n display: 'inline-block',\n ...imageStyle,\n },\n }}\n description={\n description == null || description === '' ? (\n <span style={descriptionStyle}>暂无数据</span>\n ) : typeof description === 'string' ? (\n <span style={descriptionStyle}>{description}</span>\n ) : (\n description\n )\n }\n />\n </Flex>\n );\n },\n);\n\nForwardedEmptyPlaceholder.displayName = 'Empty';\n\nexport default ForwardedEmptyPlaceholder;\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA,SAAS,OAAO,YAAY;AAE5B,OAAO,WAAW;AAClB,OAAO,cAAc;AAiBrB,IAAM,mBAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,YAAY;AACd;AAKA,IAAM,4BAA4B,MAAM;AAAA,EACtC,CAAC,EAAE,OAAO,aAAa,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,GAAe,QAAsC;AACtG,WACE,oCAAC,QAAK,KAAU,OAAO,iBAAE,SAAS,YAAa,QAAS,OAAM,UAAS,SAAQ,YAC7E;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,SAAS;AAAA,QAChB,QAAQ;AAAA,UACN,OAAO;AAAA,YACL,QAAQ;AAAA,YACR,OAAO;AAAA,YACP,SAAS;AAAA,aACN;AAAA,QAEP;AAAA,QACA,aACE,eAAe,QAAQ,gBAAgB,KACrC,oCAAC,UAAK,OAAO,oBAAkB,MAAI,IACjC,OAAO,gBAAgB,WACzB,oCAAC,UAAK,OAAO,oBAAmB,WAAY,IAE5C;AAAA;AAAA,IAGN,CACF;AAAA,EAEJ;AACF;AAEA,0BAA0B,cAAc;AAExC,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
1
  import { type PopoverProps } from 'antd';
2
2
  import React from 'react';
3
3
  import type { CategoryItem, ListItem, TerminalItem } from './typing';
4
+ export type { ListItem, CategoryItem, TerminalItem } from './typing';
4
5
  /**
5
6
  * 通用筛选器组件的 Props
6
7
  */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/business/ModCommonFilter/index.tsx"],
4
- "sourcesContent": ["import { Popover, type PopoverProps } from 'antd';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport FilterButton from './components/FilterButton';\nimport PopoverContent from './components/PopoverContent';\nimport styles from './index.module.less';\nimport type { CategoryItem, ListItem, TerminalItem } from './typing';\n\n/**\n * 通用筛选器组件的 Props\n */\nexport interface ModCommonFilterProps {\n /** 当前选中的值(code 数组),受控 */\n value: string[];\n /** 选中项变化回调 */\n onChange: (value: string[]) => void;\n /** 可选列表数据 */\n list: ListItem[];\n /** 筛选维度名称,如「品类」「品牌」 */\n title: string;\n /** 按钮/标题前缀文案,如「筛选」 */\n prefixTitle?: string;\n /** 按钮左侧图标 */\n iconPrefix?: React.ReactNode;\n /** 分类列表,有则弹层左侧展示分类 Tab */\n category?: CategoryItem[];\n /** 终端列表,有则弹层内展示终端 Tab(如全部/PC/APP) */\n terminal?: TerminalItem[];\n /** 搜索框占位文案 */\n placeholder?: string;\n /** Popover 层级 */\n zIndex?: number;\n /** Popover 弹出方向 */\n placement?: PopoverProps['placement'];\n /** 透传给 antd Popover 的额外属性 */\n popoverProps?: PopoverProps;\n /** 可选列表列数(多列网格) */\n columnCount?: number;\n /** 内容区宽度 */\n contentWidth?: number;\n /** 列表行高 */\n rowHeight?: number;\n /** 是否在名称后展示 code */\n showCode?: boolean;\n /** 可选列表中每项的自定义渲染 */\n cellRender?: (item: ListItem) => React.ReactNode;\n /** 已选列表中每项的自定义渲染 */\n checkedCellRender?: (item: ListItem) => React.ReactNode;\n /** 弹层底部备注文案或节点 */\n remark?: string | React.ReactNode;\n /** 自定义触发区域,不传则使用默认 FilterButton */\n filterChildren?: React.ReactNode;\n}\n\n/**\n * 通用筛选器:点击按钮打开 Popover,内为分类 + 可选列表 + 已选列表,确认后回调 onChange。\n */\nconst ModCommonFilter: React.FC<ModCommonFilterProps> = ({\n value,\n onChange,\n list,\n title,\n prefixTitle,\n iconPrefix,\n category,\n terminal,\n placeholder = '搜索',\n zIndex = 100,\n placement = 'bottomRight',\n columnCount = 1,\n contentWidth,\n rowHeight,\n showCode = false,\n popoverProps = {},\n cellRender,\n checkedCellRender,\n remark,\n filterChildren,\n}) => {\n const [popOpen, setPopOpen] = useState(false);\n /** 弹层内当前选中的 code 列表,打开时与 value 同步 */\n const [selected, setSelected] = useState<string[]>([]);\n /** 当前选中的分类 code,空字符串表示「全部」 */\n const [categorySelected, setCategorySelected] = useState<string>('');\n\n /** 弹层打开时用外部 value 同步 selected,保证每次打开初始为当前已选 */\n useEffect(() => {\n if (popOpen) {\n setSelected(value || []);\n }\n }, [popOpen, value]);\n\n /** 分类选项列表,头部插入「全部{title}」 */\n const useCateGory = useMemo(() => {\n const newCategory: CategoryItem[] = category ? [...category] : [];\n newCategory.unshift({\n code: '',\n name: '全部' + title,\n });\n return newCategory;\n }, [category]);\n\n /** 确认:把当前选中回传并关闭弹层 */\n const handleVerify = () => {\n onChange(selected);\n setPopOpen(false);\n };\n\n /** 取消:恢复为打开前的 value 并关闭弹层 */\n const handleClear = () => {\n setSelected(value || []);\n setPopOpen(false);\n };\n\n return (\n <Popover\n className={styles.modCommonFilter}\n open={popOpen}\n onOpenChange={(open) => setPopOpen(open)}\n title={false}\n fresh={true}\n arrow={false}\n zIndex={zIndex}\n placement={placement}\n trigger='click'\n classNames={{\n body: styles.popoverBody,\n }}\n getPopupContainer={(triggerNode) => triggerNode.parentNode as HTMLElement}\n content={\n <PopoverContent\n popOpen={popOpen}\n selected={selected}\n setSelected={setSelected}\n category={useCateGory}\n terminal={terminal}\n list={list}\n placeholder={placeholder}\n title={title}\n categorySelected={categorySelected}\n setCategorySelected={setCategorySelected}\n columnCount={columnCount}\n showCode={showCode}\n contentWidth={contentWidth}\n rowHeight={rowHeight}\n cellRender={cellRender}\n checkedCellRender={checkedCellRender}\n handleVerify={handleVerify}\n handleClear={handleClear}\n remark={remark}\n />\n }\n {...popoverProps}\n >\n {filterChildren || (\n <FilterButton\n iconPrefix={iconPrefix}\n title={title}\n prefixTitle={prefixTitle}\n value={value}\n popOpen={popOpen}\n handlePopOpen={() => setPopOpen(!popOpen)}\n handleClear={() => onChange([])}\n />\n )}\n </Popover>\n );\n};\n\nexport default ModCommonFilter;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA,SAAS,eAAkC;AAC3C,OAAO,SAAS,WAAW,SAAS,gBAAgB;AACpD,OAAO,kBAAkB;AACzB,OAAO,oBAAoB;AAC3B,OAAO,YAAY;AAoDnB,IAAM,kBAAkD,CAAC;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,eAAe,CAAC;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,CAAC,CAAC;AAErD,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAiB,EAAE;AAGnE,YAAU,MAAM;AACd,QAAI,SAAS;AACX,kBAAY,SAAS,CAAC,CAAC;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,SAAS,KAAK,CAAC;AAGnB,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,cAA8B,WAAW,CAAC,GAAG,QAAQ,IAAI,CAAC;AAChE,gBAAY,QAAQ;AAAA,MAClB,MAAM;AAAA,MACN,MAAM,OAAO;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,eAAe,MAAM;AACzB,aAAS,QAAQ;AACjB,eAAW,KAAK;AAAA,EAClB;AAGA,QAAM,cAAc,MAAM;AACxB,gBAAY,SAAS,CAAC,CAAC;AACvB,eAAW,KAAK;AAAA,EAClB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,OAAO;AAAA,MAClB,MAAM;AAAA,MACN,cAAc,CAAC,SAAS,WAAW,IAAI;AAAA,MACvC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,SAAQ;AAAA,MACR,YAAY;AAAA,QACV,MAAM,OAAO;AAAA,MACf;AAAA,MACA,mBAAmB,CAAC,gBAAgB,YAAY;AAAA,MAChD,SACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEE;AAAA,IAEH,kBACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,MAAM,WAAW,CAAC,OAAO;AAAA,QACxC,aAAa,MAAM,SAAS,CAAC,CAAC;AAAA;AAAA,IAChC;AAAA,EAEJ;AAEJ;AAEA,IAAO,0BAAQ;",
4
+ "sourcesContent": ["import { Popover, type PopoverProps } from 'antd';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport FilterButton from './components/FilterButton';\nimport PopoverContent from './components/PopoverContent';\nimport styles from './index.module.less';\nimport type { CategoryItem, ListItem, TerminalItem } from './typing';\n\nexport type { ListItem, CategoryItem, TerminalItem } from './typing';\n\n/**\n * 通用筛选器组件的 Props\n */\nexport interface ModCommonFilterProps {\n /** 当前选中的值(code 数组),受控 */\n value: string[];\n /** 选中项变化回调 */\n onChange: (value: string[]) => void;\n /** 可选列表数据 */\n list: ListItem[];\n /** 筛选维度名称,如「品类」「品牌」 */\n title: string;\n /** 按钮/标题前缀文案,如「筛选」 */\n prefixTitle?: string;\n /** 按钮左侧图标 */\n iconPrefix?: React.ReactNode;\n /** 分类列表,有则弹层左侧展示分类 Tab */\n category?: CategoryItem[];\n /** 终端列表,有则弹层内展示终端 Tab(如全部/PC/APP) */\n terminal?: TerminalItem[];\n /** 搜索框占位文案 */\n placeholder?: string;\n /** Popover 层级 */\n zIndex?: number;\n /** Popover 弹出方向 */\n placement?: PopoverProps['placement'];\n /** 透传给 antd Popover 的额外属性 */\n popoverProps?: PopoverProps;\n /** 可选列表列数(多列网格) */\n columnCount?: number;\n /** 内容区宽度 */\n contentWidth?: number;\n /** 列表行高 */\n rowHeight?: number;\n /** 是否在名称后展示 code */\n showCode?: boolean;\n /** 可选列表中每项的自定义渲染 */\n cellRender?: (item: ListItem) => React.ReactNode;\n /** 已选列表中每项的自定义渲染 */\n checkedCellRender?: (item: ListItem) => React.ReactNode;\n /** 弹层底部备注文案或节点 */\n remark?: string | React.ReactNode;\n /** 自定义触发区域,不传则使用默认 FilterButton */\n filterChildren?: React.ReactNode;\n}\n\n/**\n * 通用筛选器:点击按钮打开 Popover,内为分类 + 可选列表 + 已选列表,确认后回调 onChange。\n */\nconst ModCommonFilter: React.FC<ModCommonFilterProps> = ({\n value,\n onChange,\n list,\n title,\n prefixTitle,\n iconPrefix,\n category,\n terminal,\n placeholder = '搜索',\n zIndex = 100,\n placement = 'bottomRight',\n columnCount = 1,\n contentWidth,\n rowHeight,\n showCode = false,\n popoverProps = {},\n cellRender,\n checkedCellRender,\n remark,\n filterChildren,\n}) => {\n const [popOpen, setPopOpen] = useState(false);\n /** 弹层内当前选中的 code 列表,打开时与 value 同步 */\n const [selected, setSelected] = useState<string[]>([]);\n /** 当前选中的分类 code,空字符串表示「全部」 */\n const [categorySelected, setCategorySelected] = useState<string>('');\n\n /** 弹层打开时用外部 value 同步 selected,保证每次打开初始为当前已选 */\n useEffect(() => {\n if (popOpen) {\n setSelected(value || []);\n }\n }, [popOpen, value]);\n\n /** 分类选项列表,头部插入「全部{title}」 */\n const useCateGory = useMemo(() => {\n const newCategory: CategoryItem[] = category ? [...category] : [];\n newCategory.unshift({\n code: '',\n name: '全部' + title,\n });\n return newCategory;\n }, [category]);\n\n /** 确认:把当前选中回传并关闭弹层 */\n const handleVerify = () => {\n onChange(selected);\n setPopOpen(false);\n };\n\n /** 取消:恢复为打开前的 value 并关闭弹层 */\n const handleClear = () => {\n setSelected(value || []);\n setPopOpen(false);\n };\n\n return (\n <Popover\n className={styles.modCommonFilter}\n open={popOpen}\n onOpenChange={(open) => setPopOpen(open)}\n title={false}\n fresh={true}\n arrow={false}\n zIndex={zIndex}\n placement={placement}\n trigger='click'\n classNames={{\n body: styles.popoverBody,\n }}\n getPopupContainer={(triggerNode) => triggerNode.parentNode as HTMLElement}\n content={\n <PopoverContent\n popOpen={popOpen}\n selected={selected}\n setSelected={setSelected}\n category={useCateGory}\n terminal={terminal}\n list={list}\n placeholder={placeholder}\n title={title}\n categorySelected={categorySelected}\n setCategorySelected={setCategorySelected}\n columnCount={columnCount}\n showCode={showCode}\n contentWidth={contentWidth}\n rowHeight={rowHeight}\n cellRender={cellRender}\n checkedCellRender={checkedCellRender}\n handleVerify={handleVerify}\n handleClear={handleClear}\n remark={remark}\n />\n }\n {...popoverProps}\n >\n {filterChildren || (\n <FilterButton\n iconPrefix={iconPrefix}\n title={title}\n prefixTitle={prefixTitle}\n value={value}\n popOpen={popOpen}\n handlePopOpen={() => setPopOpen(!popOpen)}\n handleClear={() => onChange([])}\n />\n )}\n </Popover>\n );\n};\n\nexport default ModCommonFilter;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA,SAAS,eAAkC;AAC3C,OAAO,SAAS,WAAW,SAAS,gBAAgB;AACpD,OAAO,kBAAkB;AACzB,OAAO,oBAAoB;AAC3B,OAAO,YAAY;AAsDnB,IAAM,kBAAkD,CAAC;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,eAAe,CAAC;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,CAAC,CAAC;AAErD,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAiB,EAAE;AAGnE,YAAU,MAAM;AACd,QAAI,SAAS;AACX,kBAAY,SAAS,CAAC,CAAC;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,SAAS,KAAK,CAAC;AAGnB,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,cAA8B,WAAW,CAAC,GAAG,QAAQ,IAAI,CAAC;AAChE,gBAAY,QAAQ;AAAA,MAClB,MAAM;AAAA,MACN,MAAM,OAAO;AAAA,IACf,CAAC;AACD,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,eAAe,MAAM;AACzB,aAAS,QAAQ;AACjB,eAAW,KAAK;AAAA,EAClB;AAGA,QAAM,cAAc,MAAM;AACxB,gBAAY,SAAS,CAAC,CAAC;AACvB,eAAW,KAAK;AAAA,EAClB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,OAAO;AAAA,MAClB,MAAM;AAAA,MACN,cAAc,CAAC,SAAS,WAAW,IAAI;AAAA,MACvC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,SAAQ;AAAA,MACR,YAAY;AAAA,QACV,MAAM,OAAO;AAAA,MACf;AAAA,MACA,mBAAmB,CAAC,gBAAgB,YAAY;AAAA,MAChD,SACE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA,OAEE;AAAA,IAEH,kBACC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,MAAM,WAAW,CAAC,OAAO;AAAA,QACxC,aAAa,MAAM,SAAS,CAAC,CAAC;AAAA;AAAA,IAChC;AAAA,EAEJ;AAEJ;AAEA,IAAO,0BAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { type SmsLoginFormApi } from './SmsLoginForm';
3
+ export type { SmsLoginFormApi } from './SmsLoginForm';
3
4
  export type LoginType = 'qrcode' | 'sms';
4
5
  export type LoginTabItem = {
5
6
  key: LoginType;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/business/YkLoginModule/index.tsx"],
4
- "sourcesContent": ["import { LoginForm } from '@ant-design/pro-form';\nimport { Flex, message, QRCode, Tabs } from 'antd';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport SmsLoginForm, { type SmsLoginFormApi } from './SmsLoginForm';\nimport styles from './styles.module.less';\n\nexport type LoginType = 'qrcode' | 'sms';\n\nexport type LoginTabItem = {\n key: LoginType;\n label: React.ReactNode;\n};\n\nexport type QrcodeApi = {\n getQrcode: () => Promise<{ qrcode: string; url: string }>;\n scanLogin: (qrcode: string) => Promise<{\n code: number;\n data?: {\n status?: number;\n msg?: string;\n };\n }>;\n};\n\nexport type LoginModuleProps = {\n title: React.ReactNode;\n tabs: LoginTabItem[];\n defaultLoginType: LoginType;\n containerStyle?: React.CSSProperties;\n actions?: React.ReactNode | ((loginType: LoginType) => React.ReactNode);\n className?: string;\n formClassName?: string;\n tabsClassName?: string;\n inputClassName?: string;\n qrcodeClassName?: string;\n qrcodeBoxClassName?: string;\n\n onFinish: (values: Record<string, unknown>) => Promise<void>;\n\n qrcode?: {\n api: QrcodeApi;\n icon: string;\n iconSize?: number;\n size?: number;\n wrapStyle?: React.CSSProperties;\n onSuccess: () => void | Promise<void>;\n };\n\n sms?: {\n api: SmsLoginFormApi;\n appKey: string;\n };\n};\n\nconst DEFAULT_QRCODE_WRAP_STYLE: React.CSSProperties = {\n padding: 10,\n display: 'flex',\n justifyContent: 'center',\n};\n\nconst LoginModule: React.FC<LoginModuleProps> = (props) => {\n const {\n title,\n tabs,\n defaultLoginType,\n containerStyle,\n actions,\n onFinish,\n qrcode,\n className = styles.root,\n formClassName = styles.form,\n tabsClassName = styles.tabs,\n inputClassName,\n qrcodeClassName = styles.qrcode,\n qrcodeBoxClassName = styles.qrcodeBox,\n sms,\n } = props;\n\n const [loginType, setLoginType] = useState<LoginType>(defaultLoginType);\n\n const [qrcodeStatus, setQrcodeStatus] = useState<'active' | 'expired' | 'loading'>('active');\n const [qrcodeUrl, setQrcodeUrl] = useState<string>('-');\n const [qrcodeValue, setQrcodeValue] = useState<string>('');\n const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const pollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const shouldShowSubmitter = loginType !== 'qrcode';\n\n const resolvedActions = useMemo(() => {\n if (!actions) return undefined;\n return typeof actions === 'function' ? actions(loginType) : actions;\n }, [actions, loginType]);\n\n const safeClearTimers = useCallback(() => {\n if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);\n if (pollTimeoutRef.current) clearTimeout(pollTimeoutRef.current);\n pollIntervalRef.current = null;\n pollTimeoutRef.current = null;\n }, []);\n\n const handleQrcodeRefresh = useCallback(async () => {\n if (!qrcode) return;\n setQrcodeStatus('loading');\n try {\n const res = await qrcode.api.getQrcode();\n setQrcodeUrl(res.url);\n setQrcodeValue(res.qrcode);\n setQrcodeStatus('active');\n } catch {\n setQrcodeStatus('expired');\n message.error('获取二维码失败,请稍后重试');\n }\n }, [qrcode]);\n\n const enabledTabKeys = useMemo(() => new Set(tabs.map((t) => t.key)), [tabs]);\n\n useEffect(() => {\n if (enabledTabKeys.has(defaultLoginType)) {\n setLoginType(defaultLoginType);\n return;\n }\n const fallback = tabs[0]?.key;\n if (fallback) setLoginType(fallback);\n }, [defaultLoginType, enabledTabKeys, tabs]);\n\n useEffect(() => {\n if (enabledTabKeys.has(loginType)) return;\n const fallback = tabs[0]?.key;\n if (fallback) setLoginType(fallback);\n }, [enabledTabKeys, loginType, tabs]);\n\n // 切到扫码登录时刷新二维码;离开扫码登录时停止轮询并标记过期\n useEffect(() => {\n safeClearTimers();\n if (loginType !== 'qrcode') {\n setQrcodeStatus('expired');\n return;\n }\n if (!qrcode) {\n setQrcodeStatus('expired');\n return;\n }\n void handleQrcodeRefresh();\n return safeClearTimers;\n }, [handleQrcodeRefresh, loginType, qrcode, safeClearTimers]);\n\n // 扫码轮询:仅在二维码“激活 + 有值 + 在扫码 Tab”时启动\n useEffect(() => {\n safeClearTimers();\n if (!qrcode) return;\n if (loginType !== 'qrcode') return;\n if (qrcodeStatus !== 'active') return;\n if (!qrcodeValue) return;\n\n pollIntervalRef.current = setInterval(() => {\n void qrcode.api\n .scanLogin(qrcodeValue)\n .then((res) => {\n if (res.code !== 200) return;\n\n const status = res.data?.status;\n const msg = res.data?.msg ?? '扫码遇到问题,稍后重试';\n\n if (status === -1) return;\n if (status !== 1) {\n safeClearTimers();\n setQrcodeStatus('expired');\n message.error(msg, 3);\n return;\n }\n safeClearTimers();\n void qrcode.onSuccess();\n })\n .catch(() => {\n // 忽略轮询中的偶发网络错误,保持继续轮询直到超时/成功\n });\n }, 1000);\n\n pollTimeoutRef.current = setTimeout(() => {\n setQrcodeStatus('expired');\n safeClearTimers();\n }, 30000);\n\n return safeClearTimers;\n }, [loginType, qrcode, qrcodeStatus, qrcodeValue, safeClearTimers]);\n\n const tabItems = useMemo(() => tabs.map((t) => ({ key: t.key, label: t.label })), [tabs]);\n\n return (\n <div className={className} style={{ maxWidth: '500px' }}>\n <LoginForm\n className={formClassName}\n onFinish={async (values) => {\n await onFinish(values);\n }}\n title={typeof title === 'string' ? <div className={styles.title}>{title}</div> : title}\n containerStyle={containerStyle}\n submitter={shouldShowSubmitter ? undefined : (false as const)}\n actions={resolvedActions}\n >\n <Tabs\n className={tabsClassName}\n centered\n activeKey={loginType}\n onChange={(activeKey) => {\n const next = activeKey as LoginType;\n setLoginType(next);\n }}\n items={tabItems}\n />\n\n {enabledTabKeys.has('qrcode') && loginType === 'qrcode' && qrcode && (\n <div style={qrcode.wrapStyle ?? DEFAULT_QRCODE_WRAP_STYLE}>\n <div className={qrcodeBoxClassName}>\n <Flex justify='center' align='center'>\n <i className='iconfont icon-saoyisao' style={{ color: '#999999', marginRight: 10, fontSize: 14 }}></i>\n 请使用<span style={{ color: '#0A6BFD' }}>小闪扫码</span>登录\n </Flex>\n <QRCode\n icon={qrcode.icon}\n iconSize={qrcode.iconSize ?? 50}\n className={qrcodeClassName}\n size={qrcode.size ?? 240}\n value={qrcodeUrl}\n status={qrcodeStatus}\n onRefresh={handleQrcodeRefresh}\n />\n </div>\n </div>\n )}\n\n {enabledTabKeys.has('sms') && loginType === 'sms' && sms && (\n <SmsLoginForm inputClassName={inputClassName ?? ''} api={sms.api} appKey={sms.appKey} />\n )}\n </LoginForm>\n </div>\n );\n};\n\nexport default LoginModule;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { LoginForm } from '@ant-design/pro-form';\nimport { Flex, message, QRCode, Tabs } from 'antd';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport SmsLoginForm, { type SmsLoginFormApi } from './SmsLoginForm';\nimport styles from './styles.module.less';\n\nexport type { SmsLoginFormApi } from './SmsLoginForm';\n\nexport type LoginType = 'qrcode' | 'sms';\n\nexport type LoginTabItem = {\n key: LoginType;\n label: React.ReactNode;\n};\n\nexport type QrcodeApi = {\n getQrcode: () => Promise<{ qrcode: string; url: string }>;\n scanLogin: (qrcode: string) => Promise<{\n code: number;\n data?: {\n status?: number;\n msg?: string;\n };\n }>;\n};\n\nexport type LoginModuleProps = {\n title: React.ReactNode;\n tabs: LoginTabItem[];\n defaultLoginType: LoginType;\n containerStyle?: React.CSSProperties;\n actions?: React.ReactNode | ((loginType: LoginType) => React.ReactNode);\n className?: string;\n formClassName?: string;\n tabsClassName?: string;\n inputClassName?: string;\n qrcodeClassName?: string;\n qrcodeBoxClassName?: string;\n\n onFinish: (values: Record<string, unknown>) => Promise<void>;\n\n qrcode?: {\n api: QrcodeApi;\n icon: string;\n iconSize?: number;\n size?: number;\n wrapStyle?: React.CSSProperties;\n onSuccess: () => void | Promise<void>;\n };\n\n sms?: {\n api: SmsLoginFormApi;\n appKey: string;\n };\n};\n\nconst DEFAULT_QRCODE_WRAP_STYLE: React.CSSProperties = {\n padding: 10,\n display: 'flex',\n justifyContent: 'center',\n};\n\nconst LoginModule: React.FC<LoginModuleProps> = (props) => {\n const {\n title,\n tabs,\n defaultLoginType,\n containerStyle,\n actions,\n onFinish,\n qrcode,\n className = styles.root,\n formClassName = styles.form,\n tabsClassName = styles.tabs,\n inputClassName,\n qrcodeClassName = styles.qrcode,\n qrcodeBoxClassName = styles.qrcodeBox,\n sms,\n } = props;\n\n const [loginType, setLoginType] = useState<LoginType>(defaultLoginType);\n\n const [qrcodeStatus, setQrcodeStatus] = useState<'active' | 'expired' | 'loading'>('active');\n const [qrcodeUrl, setQrcodeUrl] = useState<string>('-');\n const [qrcodeValue, setQrcodeValue] = useState<string>('');\n const pollIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const pollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const shouldShowSubmitter = loginType !== 'qrcode';\n\n const resolvedActions = useMemo(() => {\n if (!actions) return undefined;\n return typeof actions === 'function' ? actions(loginType) : actions;\n }, [actions, loginType]);\n\n const safeClearTimers = useCallback(() => {\n if (pollIntervalRef.current) clearInterval(pollIntervalRef.current);\n if (pollTimeoutRef.current) clearTimeout(pollTimeoutRef.current);\n pollIntervalRef.current = null;\n pollTimeoutRef.current = null;\n }, []);\n\n const handleQrcodeRefresh = useCallback(async () => {\n if (!qrcode) return;\n setQrcodeStatus('loading');\n try {\n const res = await qrcode.api.getQrcode();\n setQrcodeUrl(res.url);\n setQrcodeValue(res.qrcode);\n setQrcodeStatus('active');\n } catch {\n setQrcodeStatus('expired');\n message.error('获取二维码失败,请稍后重试');\n }\n }, [qrcode]);\n\n const enabledTabKeys = useMemo(() => new Set(tabs.map((t) => t.key)), [tabs]);\n\n useEffect(() => {\n if (enabledTabKeys.has(defaultLoginType)) {\n setLoginType(defaultLoginType);\n return;\n }\n const fallback = tabs[0]?.key;\n if (fallback) setLoginType(fallback);\n }, [defaultLoginType, enabledTabKeys, tabs]);\n\n useEffect(() => {\n if (enabledTabKeys.has(loginType)) return;\n const fallback = tabs[0]?.key;\n if (fallback) setLoginType(fallback);\n }, [enabledTabKeys, loginType, tabs]);\n\n // 切到扫码登录时刷新二维码;离开扫码登录时停止轮询并标记过期\n useEffect(() => {\n safeClearTimers();\n if (loginType !== 'qrcode') {\n setQrcodeStatus('expired');\n return;\n }\n if (!qrcode) {\n setQrcodeStatus('expired');\n return;\n }\n void handleQrcodeRefresh();\n return safeClearTimers;\n }, [handleQrcodeRefresh, loginType, qrcode, safeClearTimers]);\n\n // 扫码轮询:仅在二维码“激活 + 有值 + 在扫码 Tab”时启动\n useEffect(() => {\n safeClearTimers();\n if (!qrcode) return;\n if (loginType !== 'qrcode') return;\n if (qrcodeStatus !== 'active') return;\n if (!qrcodeValue) return;\n\n pollIntervalRef.current = setInterval(() => {\n void qrcode.api\n .scanLogin(qrcodeValue)\n .then((res) => {\n if (res.code !== 200) return;\n\n const status = res.data?.status;\n const msg = res.data?.msg ?? '扫码遇到问题,稍后重试';\n\n if (status === -1) return;\n if (status !== 1) {\n safeClearTimers();\n setQrcodeStatus('expired');\n message.error(msg, 3);\n return;\n }\n safeClearTimers();\n void qrcode.onSuccess();\n })\n .catch(() => {\n // 忽略轮询中的偶发网络错误,保持继续轮询直到超时/成功\n });\n }, 1000);\n\n pollTimeoutRef.current = setTimeout(() => {\n setQrcodeStatus('expired');\n safeClearTimers();\n }, 30000);\n\n return safeClearTimers;\n }, [loginType, qrcode, qrcodeStatus, qrcodeValue, safeClearTimers]);\n\n const tabItems = useMemo(() => tabs.map((t) => ({ key: t.key, label: t.label })), [tabs]);\n\n return (\n <div className={className} style={{ maxWidth: '500px' }}>\n <LoginForm\n className={formClassName}\n onFinish={async (values) => {\n await onFinish(values);\n }}\n title={typeof title === 'string' ? <div className={styles.title}>{title}</div> : title}\n containerStyle={containerStyle}\n submitter={shouldShowSubmitter ? undefined : (false as const)}\n actions={resolvedActions}\n >\n <Tabs\n className={tabsClassName}\n centered\n activeKey={loginType}\n onChange={(activeKey) => {\n const next = activeKey as LoginType;\n setLoginType(next);\n }}\n items={tabItems}\n />\n\n {enabledTabKeys.has('qrcode') && loginType === 'qrcode' && qrcode && (\n <div style={qrcode.wrapStyle ?? DEFAULT_QRCODE_WRAP_STYLE}>\n <div className={qrcodeBoxClassName}>\n <Flex justify='center' align='center'>\n <i className='iconfont icon-saoyisao' style={{ color: '#999999', marginRight: 10, fontSize: 14 }}></i>\n 请使用<span style={{ color: '#0A6BFD' }}>小闪扫码</span>登录\n </Flex>\n <QRCode\n icon={qrcode.icon}\n iconSize={qrcode.iconSize ?? 50}\n className={qrcodeClassName}\n size={qrcode.size ?? 240}\n value={qrcodeUrl}\n status={qrcodeStatus}\n onRefresh={handleQrcodeRefresh}\n />\n </div>\n </div>\n )}\n\n {enabledTabKeys.has('sms') && loginType === 'sms' && sms && (\n <SmsLoginForm inputClassName={inputClassName ?? ''} api={sms.api} appKey={sms.appKey} />\n )}\n </LoginForm>\n </div>\n );\n};\n\nexport default LoginModule;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,iBAAiB;AAC1B,SAAS,MAAM,SAAS,QAAQ,YAAY;AAC5C,OAAO,SAAS,aAAa,WAAW,SAAS,QAAQ,gBAAgB;AACzE,OAAO,kBAA4C;AACnD,OAAO,YAAY;AAoDnB,IAAM,4BAAiD;AAAA,EACrD,SAAS;AAAA,EACT,SAAS;AAAA,EACT,gBAAgB;AAClB;AAEA,IAAM,cAA0C,CAAC,UAAU;AA9D3D;AA+DE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,IACnB,gBAAgB,OAAO;AAAA,IACvB,gBAAgB,OAAO;AAAA,IACvB;AAAA,IACA,kBAAkB,OAAO;AAAA,IACzB,qBAAqB,OAAO;AAAA,IAC5B;AAAA,EACF,IAAI;AAEJ,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB,gBAAgB;AAEtE,QAAM,CAAC,cAAc,eAAe,IAAI,SAA2C,QAAQ;AAC3F,QAAM,CAAC,WAAW,YAAY,IAAI,SAAiB,GAAG;AACtD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAiB,EAAE;AACzD,QAAM,kBAAkB,OAA8C,IAAI;AAC1E,QAAM,iBAAiB,OAA6C,IAAI;AACxE,QAAM,sBAAsB,cAAc;AAE1C,QAAM,kBAAkB,QAAQ,MAAM;AACpC,QAAI,CAAC;AAAS,aAAO;AACrB,WAAO,OAAO,YAAY,aAAa,QAAQ,SAAS,IAAI;AAAA,EAC9D,GAAG,CAAC,SAAS,SAAS,CAAC;AAEvB,QAAM,kBAAkB,YAAY,MAAM;AACxC,QAAI,gBAAgB;AAAS,oBAAc,gBAAgB,OAAO;AAClE,QAAI,eAAe;AAAS,mBAAa,eAAe,OAAO;AAC/D,oBAAgB,UAAU;AAC1B,mBAAe,UAAU;AAAA,EAC3B,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAsB,YAAY,MAAY;AAClD,QAAI,CAAC;AAAQ;AACb,oBAAgB,SAAS;AACzB,QAAI;AACF,YAAM,MAAM,MAAM,OAAO,IAAI,UAAU;AACvC,mBAAa,IAAI,GAAG;AACpB,qBAAe,IAAI,MAAM;AACzB,sBAAgB,QAAQ;AAAA,IAC1B,SAAQ,GAAN;AACA,sBAAgB,SAAS;AACzB,cAAQ,MAAM,eAAe;AAAA,IAC/B;AAAA,EACF,IAAG,CAAC,MAAM,CAAC;AAEX,QAAM,iBAAiB,QAAQ,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AAE5E,YAAU,MAAM;AArHlB,QAAAA;AAsHI,QAAI,eAAe,IAAI,gBAAgB,GAAG;AACxC,mBAAa,gBAAgB;AAC7B;AAAA,IACF;AACA,UAAM,YAAWA,MAAA,KAAK,CAAC,MAAN,gBAAAA,IAAS;AAC1B,QAAI;AAAU,mBAAa,QAAQ;AAAA,EACrC,GAAG,CAAC,kBAAkB,gBAAgB,IAAI,CAAC;AAE3C,YAAU,MAAM;AA9HlB,QAAAA;AA+HI,QAAI,eAAe,IAAI,SAAS;AAAG;AACnC,UAAM,YAAWA,MAAA,KAAK,CAAC,MAAN,gBAAAA,IAAS;AAC1B,QAAI;AAAU,mBAAa,QAAQ;AAAA,EACrC,GAAG,CAAC,gBAAgB,WAAW,IAAI,CAAC;AAGpC,YAAU,MAAM;AACd,oBAAgB;AAChB,QAAI,cAAc,UAAU;AAC1B,sBAAgB,SAAS;AACzB;AAAA,IACF;AACA,QAAI,CAAC,QAAQ;AACX,sBAAgB,SAAS;AACzB;AAAA,IACF;AACA,SAAK,oBAAoB;AACzB,WAAO;AAAA,EACT,GAAG,CAAC,qBAAqB,WAAW,QAAQ,eAAe,CAAC;AAG5D,YAAU,MAAM;AACd,oBAAgB;AAChB,QAAI,CAAC;AAAQ;AACb,QAAI,cAAc;AAAU;AAC5B,QAAI,iBAAiB;AAAU;AAC/B,QAAI,CAAC;AAAa;AAElB,oBAAgB,UAAU,YAAY,MAAM;AAC1C,WAAK,OAAO,IACT,UAAU,WAAW,EACrB,KAAK,CAAC,QAAQ;AA9JvB,YAAAA,KAAAC,KAAAC;AA+JU,YAAI,IAAI,SAAS;AAAK;AAEtB,cAAM,UAASF,MAAA,IAAI,SAAJ,gBAAAA,IAAU;AACzB,cAAM,OAAME,OAAAD,MAAA,IAAI,SAAJ,gBAAAA,IAAU,QAAV,OAAAC,MAAiB;AAE7B,YAAI,WAAW;AAAI;AACnB,YAAI,WAAW,GAAG;AAChB,0BAAgB;AAChB,0BAAgB,SAAS;AACzB,kBAAQ,MAAM,KAAK,CAAC;AACpB;AAAA,QACF;AACA,wBAAgB;AAChB,aAAK,OAAO,UAAU;AAAA,MACxB,CAAC,EACA,MAAM,MAAM;AAAA,MAEb,CAAC;AAAA,IACL,GAAG,GAAI;AAEP,mBAAe,UAAU,WAAW,MAAM;AACxC,sBAAgB,SAAS;AACzB,sBAAgB;AAAA,IAClB,GAAG,GAAK;AAER,WAAO;AAAA,EACT,GAAG,CAAC,WAAW,QAAQ,cAAc,aAAa,eAAe,CAAC;AAElE,QAAM,WAAW,QAAQ,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC;AAExF,SACE,oCAAC,SAAI,WAAsB,OAAO,EAAE,UAAU,QAAQ,KACpD;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,MACX,UAAU,CAAO,WAAW;AAC1B,cAAM,SAAS,MAAM;AAAA,MACvB;AAAA,MACA,OAAO,OAAO,UAAU,WAAW,oCAAC,SAAI,WAAW,OAAO,SAAQ,KAAM,IAAS;AAAA,MACjF;AAAA,MACA,WAAW,sBAAsB,SAAa;AAAA,MAC9C,SAAS;AAAA;AAAA,IAET;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX,UAAQ;AAAA,QACR,WAAW;AAAA,QACX,UAAU,CAAC,cAAc;AACvB,gBAAM,OAAO;AACb,uBAAa,IAAI;AAAA,QACnB;AAAA,QACA,OAAO;AAAA;AAAA,IACT;AAAA,IAEC,eAAe,IAAI,QAAQ,KAAK,cAAc,YAAY,UACzD,oCAAC,SAAI,QAAO,YAAO,cAAP,YAAoB,6BAC9B,oCAAC,SAAI,WAAW,sBACd,oCAAC,QAAK,SAAQ,UAAS,OAAM,YAC3B,oCAAC,OAAE,WAAU,0BAAyB,OAAO,EAAE,OAAO,WAAW,aAAa,IAAI,UAAU,GAAG,GAAG,GAAI,OACnG,oCAAC,UAAK,OAAO,EAAE,OAAO,UAAU,KAAG,MAAI,GAAO,IACnD,GACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,OAAO;AAAA,QACb,WAAU,YAAO,aAAP,YAAmB;AAAA,QAC7B,WAAW;AAAA,QACX,OAAM,YAAO,SAAP,YAAe;AAAA,QACrB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAW;AAAA;AAAA,IACb,CACF,CACF;AAAA,IAGD,eAAe,IAAI,KAAK,KAAK,cAAc,SAAS,OACnD,oCAAC,gBAAa,gBAAgB,0CAAkB,IAAI,KAAK,IAAI,KAAK,QAAQ,IAAI,QAAQ;AAAA,EAE1F,CACF;AAEJ;AAEA,IAAO,wBAAQ;",
6
6
  "names": ["_a", "_b", "_c"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import React, { type FC } from 'react';
2
2
  /** 项目选项项 */
3
- type OptionItem = {
3
+ export type OptionItem = {
4
4
  /** 项目名称 */
5
5
  label: string;
6
6
  /** 项目 ID */
@@ -17,7 +17,7 @@ type OptionItem = {
17
17
  closed?: boolean;
18
18
  };
19
19
  /** 项目选择器 Props */
20
- type PageTypes = {
20
+ export type YkPorjectSelectProps = {
21
21
  /** 当前选中的项目 ID */
22
22
  value: string | number;
23
23
  /** 项目选项列表 */
@@ -47,5 +47,5 @@ type PageTypes = {
47
47
  * />
48
48
  * ```
49
49
  */
50
- declare const YkPorjectSelect: FC<PageTypes>;
50
+ declare const YkPorjectSelect: FC<YkPorjectSelectProps>;
51
51
  export default YkPorjectSelect;
@@ -29,32 +29,12 @@ var __objRest = (source, exclude) => {
29
29
  }
30
30
  return target;
31
31
  };
32
- var __async = (__this, __arguments, generator) => {
33
- return new Promise((resolve, reject) => {
34
- var fulfilled = (value) => {
35
- try {
36
- step(generator.next(value));
37
- } catch (e) {
38
- reject(e);
39
- }
40
- };
41
- var rejected = (value) => {
42
- try {
43
- step(generator.throw(value));
44
- } catch (e) {
45
- reject(e);
46
- }
47
- };
48
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
- step((generator = generator.apply(__this, __arguments)).next());
50
- });
51
- };
52
32
 
53
33
  // src/business/YkPorjectSelect/index.tsx
54
34
  import { SearchOutlined } from "@ant-design/icons";
55
35
  import { ConfigProvider, Empty, Flex, Input, Popover, Rate, Tabs, Tooltip } from "antd";
56
36
  import classNames from "classnames";
57
- import React, { useEffect, useMemo, useRef, useState } from "react";
37
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
58
38
  import { Scrollbars } from "react-custom-scrollbars-2";
59
39
  import TextWithTooltip from "../../components/TextWithToolTip";
60
40
  import iconProductDefault from "./icon-product.png";
@@ -63,7 +43,7 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
63
43
  const [open, setOpen] = useState(false);
64
44
  const [status, setStatus] = useState("1");
65
45
  const [searchKey, setSearchKey] = useState("");
66
- const [pageHeight, setPageHeight] = useState(1e3);
46
+ const [pageHeight, setPageHeight] = useState(typeof window !== "undefined" ? window.innerHeight : 1e3);
67
47
  const [localOptions, setLocalOptions] = useState(options);
68
48
  const searchInputRef = useRef(null);
69
49
  useEffect(() => {
@@ -109,8 +89,8 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
109
89
  const handleTabChange = (tabKey) => {
110
90
  setStatus(tabKey);
111
91
  };
112
- const handleStarChange = (item, val) => __async(void 0, null, function* () {
113
- void (followedCallback == null ? void 0 : followedCallback(item, val === 1));
92
+ const handleStarChange = (item, val) => {
93
+ followedCallback == null ? void 0 : followedCallback(item, val === 1);
114
94
  setLocalOptions(
115
95
  (prev) => prev.map((p) => {
116
96
  if (p.value === item.value) {
@@ -119,15 +99,14 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
119
99
  return p;
120
100
  })
121
101
  );
122
- });
123
- const handleResize = () => {
124
- const height = window.innerHeight;
125
- setPageHeight(height);
126
102
  };
103
+ const handleResize = useCallback(() => {
104
+ setPageHeight(window.innerHeight);
105
+ }, []);
127
106
  useEffect(() => {
128
107
  window.addEventListener("resize", handleResize);
129
108
  return () => window.removeEventListener("resize", handleResize);
130
- }, []);
109
+ }, [handleResize]);
131
110
  const renderItem = (item) => {
132
111
  const isDisabled = !item.followed && followedOptions.length >= 6;
133
112
  return /* @__PURE__ */ React.createElement(Flex, { justify: "space-between", align: "center" }, /* @__PURE__ */ React.createElement("span", { className: styles.contentItemSpan, onClick: () => onChange(item.value) }, /* @__PURE__ */ React.createElement("img", { className: styles.contentItemSpanIcon, src: (item == null ? void 0 : item.icon) ? item.icon : iconProductDefault }), /* @__PURE__ */ React.createElement("div", { className: styles.contentItemSpanDev }, /* @__PURE__ */ React.createElement("div", { className: styles.contentItemSpanProName }, /* @__PURE__ */ React.createElement(
@@ -156,7 +135,7 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
156
135
  if (isDisabled) {
157
136
  return;
158
137
  }
159
- void handleStarChange(item, item.followed ? 0 : 1);
138
+ handleStarChange(item, item.followed ? 0 : 1);
160
139
  }
161
140
  },
162
141
  /* @__PURE__ */ React.createElement(
@@ -206,7 +185,7 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
206
185
  placement: "bottomLeft",
207
186
  styles: { body: { color: "#333" } }
208
187
  },
209
- /* @__PURE__ */ React.createElement("div", { key: item.value, className: styles.ykPorjectSelectFollowedItem }, /* @__PURE__ */ React.createElement("img", { className: styles.ykPorjectSelectFollowedItemIcon, src: item.icon, alt: item.label }), /* @__PURE__ */ React.createElement("div", { className: styles.closeIcon, onClick: () => void handleStarChange(item, 0) }))
188
+ /* @__PURE__ */ React.createElement("div", { key: item.value, className: styles.ykPorjectSelectFollowedItem }, /* @__PURE__ */ React.createElement("img", { className: styles.ykPorjectSelectFollowedItemIcon, src: item.icon || iconProductDefault, alt: item.label }), /* @__PURE__ */ React.createElement("div", { className: styles.closeIcon, onClick: () => handleStarChange(item, 0) }))
210
189
  )))), /* @__PURE__ */ React.createElement(
211
190
  Tabs,
212
191
  {
@@ -216,27 +195,34 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
216
195
  activeKey: status,
217
196
  items: tabs
218
197
  }
219
- ), localOptions.length === 0 ? /* @__PURE__ */ React.createElement(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE }) : /* @__PURE__ */ React.createElement("div", { className: styles.ykPorjectSelectListSection }, /* @__PURE__ */ React.createElement("div", { className: styles.contentHeader }, "全部项目"), /* @__PURE__ */ React.createElement(
220
- Scrollbars,
221
- {
222
- className: styles.ykPorjectSelectScrollBarsBox,
223
- autoHeight: true,
224
- autoHide: true,
225
- autoHeightMax: Math.min(450, pageHeight - 310),
226
- renderThumbVertical: (_a) => {
227
- var _b = _a, { style } = _b, props = __objRest(_b, ["style"]);
228
- return /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({}, props), { style: __spreadProps(__spreadValues({}, style), { background: "#EEEEEE", borderRadius: 3, width: 6 }) }));
229
- }
230
- },
231
- localOptions.sort((a, b) => (b.recent_visit ? 1 : 0) - (a.recent_visit ? 1 : 0)).map((item) => /* @__PURE__ */ React.createElement(
232
- "div",
198
+ ), (() => {
199
+ const searched = searchKey ? localOptions.filter(
200
+ (item) => item.label.toLowerCase().includes(searchKey.toLowerCase()) || String(item.value).includes(searchKey)
201
+ ) : localOptions;
202
+ const filtered = searchKey ? searched : searched.filter((item) => status === "1" ? !item.closed : item.closed);
203
+ const sorted = [...filtered].sort((a, b) => (b.recent_visit ? 1 : 0) - (a.recent_visit ? 1 : 0));
204
+ return sorted.length === 0 ? /* @__PURE__ */ React.createElement(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE }) : /* @__PURE__ */ React.createElement("div", { className: styles.ykPorjectSelectListSection }, /* @__PURE__ */ React.createElement("div", { className: styles.contentHeader }, "全部项目"), /* @__PURE__ */ React.createElement(
205
+ Scrollbars,
233
206
  {
234
- key: item.value,
235
- className: classNames(styles.contentItem, item.value === value ? styles.contentItemActive : "")
207
+ className: styles.ykPorjectSelectScrollBarsBox,
208
+ autoHeight: true,
209
+ autoHide: true,
210
+ autoHeightMax: Math.min(450, pageHeight - 310),
211
+ renderThumbVertical: (_a) => {
212
+ var _b = _a, { style } = _b, props = __objRest(_b, ["style"]);
213
+ return /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({}, props), { style: __spreadProps(__spreadValues({}, style), { background: "#EEEEEE", borderRadius: 3, width: 6 }) }));
214
+ }
236
215
  },
237
- renderItem(item)
238
- ))
239
- )));
216
+ sorted.map((item) => /* @__PURE__ */ React.createElement(
217
+ "div",
218
+ {
219
+ key: item.value,
220
+ className: classNames(styles.contentItem, item.value === value ? styles.contentItemActive : "")
221
+ },
222
+ renderItem(item)
223
+ ))
224
+ ));
225
+ })());
240
226
  return /* @__PURE__ */ React.createElement(
241
227
  Popover,
242
228
  {
@@ -250,7 +236,7 @@ var YkPorjectSelect = ({ value, options, onChange, followedCallback, slot, custo
250
236
  getPopupContainer: (triggerNode) => triggerNode.parentNode,
251
237
  autoAdjustOverflow: false
252
238
  },
253
- customShow ? customShow : /* @__PURE__ */ React.createElement("div", { className: styles.ykPorjectSelectShow }, /* @__PURE__ */ React.createElement("img", { className: styles.ykPorjectSelectShowIcon, src: activeItem == null ? void 0 : activeItem.icon, alt: activeItem == null ? void 0 : activeItem.label }), /* @__PURE__ */ React.createElement("span", { className: styles.ykPorjectSelectShowText }, activeItem == null ? void 0 : activeItem.label), /* @__PURE__ */ React.createElement("i", { className: "iconfont icon-xiala" }))
239
+ customShow ? customShow : /* @__PURE__ */ React.createElement("div", { className: styles.ykPorjectSelectShow }, /* @__PURE__ */ React.createElement("img", { className: styles.ykPorjectSelectShowIcon, src: (activeItem == null ? void 0 : activeItem.icon) || iconProductDefault, alt: activeItem == null ? void 0 : activeItem.label }), /* @__PURE__ */ React.createElement("span", { className: styles.ykPorjectSelectShowText }, activeItem == null ? void 0 : activeItem.label), /* @__PURE__ */ React.createElement("i", { className: "iconfont icon-xiala" }))
254
240
  );
255
241
  };
256
242
  var YkPorjectSelect_default = YkPorjectSelect;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/business/YkPorjectSelect/index.tsx"],
4
- "sourcesContent": ["import { SearchOutlined } from '@ant-design/icons';\nimport type { InputRef } from 'antd';\nimport { ConfigProvider, Empty, Flex, Input, Popover, Rate, Tabs, Tooltip } from 'antd';\nimport classNames from 'classnames';\nimport React, { type FC, useEffect, useMemo, useRef, useState } from 'react';\nimport { Scrollbars } from 'react-custom-scrollbars-2';\nimport TextWithTooltip from '@/components/TextWithToolTip';\nimport iconProductDefault from './icon-product.png';\nimport styles from './index.module.less';\n\n/** 项目选项项 */\ntype OptionItem = {\n /** 项目名称 */\n label: string;\n /** 项目 ID */\n value: string | number;\n /** 项目图标 URL */\n icon: string;\n /** 是否已关注 */\n followed?: boolean;\n /** 关注排序索引 */\n follow_index?: number;\n /** 是否最近访问 */\n recent_visit?: boolean;\n /** 是否已关服 */\n closed?: boolean;\n};\n\n/** 项目选择器 Props */\ntype PageTypes = {\n /** 当前选中的项目 ID */\n value: string | number;\n /** 项目选项列表 */\n options: OptionItem[];\n /** 选中项目变化时的回调 */\n onChange: (value: string | number) => void;\n /** 关注/取消关注时的回调 */\n followedCallback?: (item: OptionItem, bool: boolean) => void;\n /** 弹层内自定义插槽,渲染在搜索框下方、关注项目上方 */\n slot?: React.ReactNode;\n /** 自定义触发元素,替代默认的「图标+名称+下拉箭头」展示 */\n customShow?: React.ReactNode;\n};\n\n/**\n * 项目选择器\n *\n * 支持搜索、关注/取消关注(最多6个)、在营/关服切换。\n * 弹层展开时自动聚焦搜索框,使用 preventScroll 避免页面滚动。\n *\n * @example\n * ```tsx\n * <YkPorjectSelect\n * value={projectId}\n * options={options}\n * onChange={setProjectId}\n * followedCallback={(item, followed) => api.follow(item.value, followed)}\n * />\n * ```\n */\nconst YkPorjectSelect: FC<PageTypes> = ({ value, options, onChange, followedCallback, slot, customShow }) => {\n const [open, setOpen] = useState(false);\n const [status, setStatus] = useState<string>('1');\n const [searchKey, setSearchKey] = useState('');\n const [pageHeight, setPageHeight] = useState<number>(1000);\n const [localOptions, setLocalOptions] = useState<OptionItem[]>(options);\n const searchInputRef = useRef<InputRef>(null);\n\n useEffect(() => {\n setLocalOptions(options);\n }, [options]);\n\n /** 弹层展开时聚焦搜索框,使用 preventScroll 避免浏览器滚动到顶部;延迟等待 Popover 内容挂载 */\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (open) {\n timer = setTimeout(() => {\n searchInputRef.current?.input?.focus({ preventScroll: true });\n }, 0);\n }\n return () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n };\n }, [open]);\n\n /** 在营/关服数量统计 */\n const stateCount = useMemo(() => {\n return localOptions.reduce(\n (acc, item) => {\n const statusClosed = item.closed ? 2 : 1;\n if (!acc[statusClosed]) {\n acc[statusClosed] = 0;\n }\n acc[statusClosed] += 1;\n return acc;\n },\n {} as { [key: string]: number },\n );\n }, [localOptions]);\n\n /** 在营/关服 Tab 配置 */\n const tabs = [\n { key: '1', label: `在营(${stateCount['1'] || 0})` },\n { key: '2', label: `关服(${stateCount['2'] || 0})` },\n ];\n\n /** 当前选中的项目(用于展示图标与名称) */\n const activeItem = useMemo(() => {\n return localOptions.find((item) => item.value === value);\n }, [localOptions, value]);\n\n /** 已关注的项目列表(顶部展示、用于计算关注数限制) */\n const followedOptions = useMemo(() => {\n return localOptions.filter((item) => item.followed);\n }, [localOptions]);\n\n // 切换在营/关服\n const handleTabChange = (tabKey: string) => {\n setStatus(tabKey);\n };\n\n // 点击关注或取消关注\n const handleStarChange = async (item: OptionItem, val: number) => {\n void followedCallback?.(item, val === 1);\n setLocalOptions((prev) =>\n prev.map((p) => {\n if (p.value === item.value) {\n return { ...p, followed: val === 1 };\n }\n return p;\n }),\n );\n };\n\n const handleResize = () => {\n const height = window.innerHeight;\n setPageHeight(height);\n };\n\n useEffect(() => {\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, []);\n\n /** 渲染单个项目行(名称、ID、关注星标) */\n const renderItem = (item: OptionItem) => {\n const isDisabled = !item.followed && followedOptions.length >= 6;\n return (\n <Flex justify='space-between' align='center'>\n <span className={styles.contentItemSpan} onClick={() => onChange(item.value)}>\n <img className={styles.contentItemSpanIcon} src={item?.icon ? item.icon : iconProductDefault} />\n <div className={styles.contentItemSpanDev}>\n <div className={styles.contentItemSpanProName}>\n <TextWithTooltip\n text={item.label}\n width='100%'\n maxWidth={175}\n arrow={true}\n color='#fff'\n styles={{ body: { color: '#333' } }}\n ></TextWithTooltip>\n {item.recent_visit ? <span className={styles.recentVisit}>最近访问</span> : null}\n </div>\n <div className={styles.contentItemSpanProId}>ID: {item.value}</div>\n </div>\n </span>\n <Tooltip\n title={isDisabled ? '最多关注6个项目' : item.followed ? '取消关注' : '关注'}\n color='#fff'\n placement='right'\n styles={{ body: { color: '#333' } }}\n >\n <label\n className={classNames(styles.contentItemStar, isDisabled && styles.contentItemStarDisabled)}\n onClick={() => {\n if (isDisabled) {\n return;\n }\n void handleStarChange(item, item.followed ? 0 : 1);\n }}\n >\n <ConfigProvider\n theme={{\n components: {\n Rate: {\n starBg: '#dcdbdb',\n },\n },\n }}\n >\n <Rate\n style={{\n fontSize: 14,\n color: isDisabled ? 'rgba(0, 0, 0, 0.06)' : '#FFB401',\n opacity: item.followed || followedOptions.length === 0 ? 1 : 0,\n }}\n value={item.followed ? 1 : 0}\n count={1}\n />\n </ConfigProvider>\n </label>\n </Tooltip>\n </Flex>\n );\n };\n\n /** 弹层内容:搜索、slot、关注区、Tab、项目列表 */\n const content = (\n <div className={styles.ykPorjectSelectContent}>\n <div className={styles.ykPorjectSelectHeader}>\n <Input\n ref={searchInputRef}\n className={styles.ykPorjectSelectSearchInput}\n prefix={<SearchOutlined style={{ color: '#999', marginRight: '10px' }} />}\n value={searchKey}\n onChange={(e) => setSearchKey(e.target.value)}\n allowClear\n placeholder='请输入项目ID/名称'\n />\n </div>\n {slot && <div className={styles.ykPorjectSelectSoltContainer}>{slot}</div>}\n <div className={styles.ykPorjectSelectFollowed}>\n <div className={styles.contentHeader}>关注项目</div>\n <div className={styles.ykPorjectSelectFollowedList}>\n {followedOptions.map((item) => (\n <Tooltip\n key={item.value}\n title={\n <>\n <div style={{ fontSize: 14, color: '#555555' }}>{item.label}</div>\n <div style={{ fontSize: 12, color: '#999' }}>ID: {item.value}</div>\n </>\n }\n color='#fff'\n placement='bottomLeft'\n styles={{ body: { color: '#333' } }}\n >\n <div key={item.value} className={styles.ykPorjectSelectFollowedItem}>\n <img className={styles.ykPorjectSelectFollowedItemIcon} src={item.icon} alt={item.label} />\n <div className={styles.closeIcon} onClick={() => void handleStarChange(item, 0)} />\n </div>\n </Tooltip>\n ))}\n </div>\n </div>\n <Tabs\n className={styles.ykPorjectSelectProductPanelTabs}\n centered\n onChange={handleTabChange}\n activeKey={status}\n items={tabs}\n ></Tabs>\n {localOptions.length === 0 ? (\n <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />\n ) : (\n <div className={styles.ykPorjectSelectListSection}>\n <div className={styles.contentHeader}>全部项目</div>\n <Scrollbars\n className={styles.ykPorjectSelectScrollBarsBox}\n autoHeight\n autoHide\n autoHeightMax={Math.min(450, pageHeight - 310)}\n renderThumbVertical={({ style, ...props }) => (\n <div {...props} style={{ ...style, background: '#EEEEEE', borderRadius: 3, width: 6 }} />\n )}\n >\n {localOptions\n .sort((a, b) => (b.recent_visit ? 1 : 0) - (a.recent_visit ? 1 : 0))\n .map((item) => (\n <div\n key={item.value}\n className={classNames(styles.contentItem, item.value === value ? styles.contentItemActive : '')}\n >\n {renderItem(item)}\n </div>\n ))}\n </Scrollbars>\n </div>\n )}\n </div>\n );\n\n return (\n <Popover\n className={styles.ykPorjectSelect}\n styles={{ body: { borderRadius: 4, padding: 0 } }}\n content={content}\n placement='bottom'\n trigger='click'\n open={open}\n onOpenChange={setOpen}\n getPopupContainer={(triggerNode: HTMLElement) => triggerNode.parentNode as HTMLElement}\n autoAdjustOverflow={false}\n >\n {customShow ? (\n customShow\n ) : (\n <div className={styles.ykPorjectSelectShow}>\n <img className={styles.ykPorjectSelectShowIcon} src={activeItem?.icon} alt={activeItem?.label} />\n <span className={styles.ykPorjectSelectShowText}>{activeItem?.label}</span>\n <i className='iconfont icon-xiala' />\n </div>\n )}\n </Popover>\n );\n};\n\nexport default YkPorjectSelect;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { SearchOutlined } from '@ant-design/icons';\nimport type { InputRef } from 'antd';\nimport { ConfigProvider, Empty, Flex, Input, Popover, Rate, Tabs, Tooltip } from 'antd';\nimport classNames from 'classnames';\nimport React, { type FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Scrollbars } from 'react-custom-scrollbars-2';\nimport TextWithTooltip from '@/components/TextWithToolTip';\nimport iconProductDefault from './icon-product.png';\nimport styles from './index.module.less';\n\n/** 项目选项项 */\nexport type OptionItem = {\n /** 项目名称 */\n label: string;\n /** 项目 ID */\n value: string | number;\n /** 项目图标 URL */\n icon: string;\n /** 是否已关注 */\n followed?: boolean;\n /** 关注排序索引 */\n follow_index?: number;\n /** 是否最近访问 */\n recent_visit?: boolean;\n /** 是否已关服 */\n closed?: boolean;\n};\n\n/** 项目选择器 Props */\nexport type YkPorjectSelectProps = {\n /** 当前选中的项目 ID */\n value: string | number;\n /** 项目选项列表 */\n options: OptionItem[];\n /** 选中项目变化时的回调 */\n onChange: (value: string | number) => void;\n /** 关注/取消关注时的回调 */\n followedCallback?: (item: OptionItem, bool: boolean) => void;\n /** 弹层内自定义插槽,渲染在搜索框下方、关注项目上方 */\n slot?: React.ReactNode;\n /** 自定义触发元素,替代默认的「图标+名称+下拉箭头」展示 */\n customShow?: React.ReactNode;\n};\n\n/**\n * 项目选择器\n *\n * 支持搜索、关注/取消关注(最多6个)、在营/关服切换。\n * 弹层展开时自动聚焦搜索框,使用 preventScroll 避免页面滚动。\n *\n * @example\n * ```tsx\n * <YkPorjectSelect\n * value={projectId}\n * options={options}\n * onChange={setProjectId}\n * followedCallback={(item, followed) => api.follow(item.value, followed)}\n * />\n * ```\n */\nconst YkPorjectSelect: FC<YkPorjectSelectProps> = ({ value, options, onChange, followedCallback, slot, customShow }) => {\n const [open, setOpen] = useState(false);\n const [status, setStatus] = useState<string>('1');\n const [searchKey, setSearchKey] = useState('');\n const [pageHeight, setPageHeight] = useState<number>(typeof window !== 'undefined' ? window.innerHeight : 1000);\n const [localOptions, setLocalOptions] = useState<OptionItem[]>(options);\n const searchInputRef = useRef<InputRef>(null);\n\n useEffect(() => {\n setLocalOptions(options);\n }, [options]);\n\n /** 弹层展开时聚焦搜索框,使用 preventScroll 避免浏览器滚动到顶部;延迟等待 Popover 内容挂载 */\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n if (open) {\n timer = setTimeout(() => {\n searchInputRef.current?.input?.focus({ preventScroll: true });\n }, 0);\n }\n return () => {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n };\n }, [open]);\n\n /** 在营/关服数量统计 */\n const stateCount = useMemo(() => {\n return localOptions.reduce(\n (acc, item) => {\n const statusClosed = item.closed ? 2 : 1;\n if (!acc[statusClosed]) {\n acc[statusClosed] = 0;\n }\n acc[statusClosed] += 1;\n return acc;\n },\n {} as { [key: string]: number },\n );\n }, [localOptions]);\n\n /** 在营/关服 Tab 配置 */\n const tabs = [\n { key: '1', label: `在营(${stateCount['1'] || 0})` },\n { key: '2', label: `关服(${stateCount['2'] || 0})` },\n ];\n\n /** 当前选中的项目(用于展示图标与名称) */\n const activeItem = useMemo(() => {\n return localOptions.find((item) => item.value === value);\n }, [localOptions, value]);\n\n /** 已关注的项目列表(顶部展示、用于计算关注数限制) */\n const followedOptions = useMemo(() => {\n return localOptions.filter((item) => item.followed);\n }, [localOptions]);\n\n // 切换在营/关服\n const handleTabChange = (tabKey: string) => {\n setStatus(tabKey);\n };\n\n // 点击关注或取消关注\n const handleStarChange = (item: OptionItem, val: number) => {\n followedCallback?.(item, val === 1);\n setLocalOptions((prev) =>\n prev.map((p) => {\n if (p.value === item.value) {\n return { ...p, followed: val === 1 };\n }\n return p;\n }),\n );\n };\n\n const handleResize = useCallback(() => {\n setPageHeight(window.innerHeight);\n }, []);\n\n useEffect(() => {\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, [handleResize]);\n\n /** 渲染单个项目行(名称、ID、关注星标) */\n const renderItem = (item: OptionItem) => {\n const isDisabled = !item.followed && followedOptions.length >= 6;\n return (\n <Flex justify='space-between' align='center'>\n <span className={styles.contentItemSpan} onClick={() => onChange(item.value)}>\n <img className={styles.contentItemSpanIcon} src={item?.icon ? item.icon : iconProductDefault} />\n <div className={styles.contentItemSpanDev}>\n <div className={styles.contentItemSpanProName}>\n <TextWithTooltip\n text={item.label}\n width='100%'\n maxWidth={175}\n arrow={true}\n color='#fff'\n styles={{ body: { color: '#333' } }}\n ></TextWithTooltip>\n {item.recent_visit ? <span className={styles.recentVisit}>最近访问</span> : null}\n </div>\n <div className={styles.contentItemSpanProId}>ID: {item.value}</div>\n </div>\n </span>\n <Tooltip\n title={isDisabled ? '最多关注6个项目' : item.followed ? '取消关注' : '关注'}\n color='#fff'\n placement='right'\n styles={{ body: { color: '#333' } }}\n >\n <label\n className={classNames(styles.contentItemStar, isDisabled && styles.contentItemStarDisabled)}\n onClick={() => {\n if (isDisabled) {\n return;\n }\n handleStarChange(item, item.followed ? 0 : 1);\n }}\n >\n <ConfigProvider\n theme={{\n components: {\n Rate: {\n starBg: '#dcdbdb',\n },\n },\n }}\n >\n <Rate\n style={{\n fontSize: 14,\n color: isDisabled ? 'rgba(0, 0, 0, 0.06)' : '#FFB401',\n opacity: item.followed || followedOptions.length === 0 ? 1 : 0,\n }}\n value={item.followed ? 1 : 0}\n count={1}\n />\n </ConfigProvider>\n </label>\n </Tooltip>\n </Flex>\n );\n };\n\n /** 弹层内容:搜索、slot、关注区、Tab、项目列表 */\n const content = (\n <div className={styles.ykPorjectSelectContent}>\n <div className={styles.ykPorjectSelectHeader}>\n <Input\n ref={searchInputRef}\n className={styles.ykPorjectSelectSearchInput}\n prefix={<SearchOutlined style={{ color: '#999', marginRight: '10px' }} />}\n value={searchKey}\n onChange={(e) => setSearchKey(e.target.value)}\n allowClear\n placeholder='请输入项目ID/名称'\n />\n </div>\n {slot && <div className={styles.ykPorjectSelectSoltContainer}>{slot}</div>}\n <div className={styles.ykPorjectSelectFollowed}>\n <div className={styles.contentHeader}>关注项目</div>\n <div className={styles.ykPorjectSelectFollowedList}>\n {followedOptions.map((item) => (\n <Tooltip\n key={item.value}\n title={\n <>\n <div style={{ fontSize: 14, color: '#555555' }}>{item.label}</div>\n <div style={{ fontSize: 12, color: '#999' }}>ID: {item.value}</div>\n </>\n }\n color='#fff'\n placement='bottomLeft'\n styles={{ body: { color: '#333' } }}\n >\n <div key={item.value} className={styles.ykPorjectSelectFollowedItem}>\n <img className={styles.ykPorjectSelectFollowedItemIcon} src={item.icon || iconProductDefault} alt={item.label} />\n <div className={styles.closeIcon} onClick={() => handleStarChange(item, 0)} />\n </div>\n </Tooltip>\n ))}\n </div>\n </div>\n <Tabs\n className={styles.ykPorjectSelectProductPanelTabs}\n centered\n onChange={handleTabChange}\n activeKey={status}\n items={tabs}\n ></Tabs>\n {(() => {\n /** 搜索过滤:匹配项目名称或 ID */\n const searched = searchKey\n ? localOptions.filter(\n (item) =>\n item.label.toLowerCase().includes(searchKey.toLowerCase()) ||\n String(item.value).includes(searchKey),\n )\n : localOptions;\n /** Tab 筛选:搜索时忽略 Tab 限制以展示所有匹配结果 */\n const filtered = searchKey\n ? searched\n : searched.filter((item) => (status === '1' ? !item.closed : item.closed));\n /** 按「最近访问」排序,使用展开运算符避免就地修改原数组 */\n const sorted = [...filtered].sort((a, b) => (b.recent_visit ? 1 : 0) - (a.recent_visit ? 1 : 0));\n\n return sorted.length === 0 ? (\n <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />\n ) : (\n <div className={styles.ykPorjectSelectListSection}>\n <div className={styles.contentHeader}>全部项目</div>\n <Scrollbars\n className={styles.ykPorjectSelectScrollBarsBox}\n autoHeight\n autoHide\n autoHeightMax={Math.min(450, pageHeight - 310)}\n renderThumbVertical={({ style, ...props }) => (\n <div {...props} style={{ ...style, background: '#EEEEEE', borderRadius: 3, width: 6 }} />\n )}\n >\n {sorted.map((item) => (\n <div\n key={item.value}\n className={classNames(styles.contentItem, item.value === value ? styles.contentItemActive : '')}\n >\n {renderItem(item)}\n </div>\n ))}\n </Scrollbars>\n </div>\n );\n })()}\n </div>\n );\n\n return (\n <Popover\n className={styles.ykPorjectSelect}\n styles={{ body: { borderRadius: 4, padding: 0 } }}\n content={content}\n placement='bottom'\n trigger='click'\n open={open}\n onOpenChange={setOpen}\n getPopupContainer={(triggerNode: HTMLElement) => triggerNode.parentNode as HTMLElement}\n autoAdjustOverflow={false}\n >\n {customShow ? (\n customShow\n ) : (\n <div className={styles.ykPorjectSelectShow}>\n <img className={styles.ykPorjectSelectShowIcon} src={activeItem?.icon || iconProductDefault} alt={activeItem?.label} />\n <span className={styles.ykPorjectSelectShowText}>{activeItem?.label}</span>\n <i className='iconfont icon-xiala' />\n </div>\n )}\n </Popover>\n );\n};\n\nexport default YkPorjectSelect;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
1
  import { type ReactCodeMirrorRef } from '@uiw/react-codemirror';
2
2
  import React from 'react';
3
3
  import { type SqlDialectType } from './sql-language';
4
+ export type { SqlDialectType } from './sql-language';
4
5
  export type YkSqlEditProps = {
5
6
  value: string;
6
7
  previewValue?: string;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/business/YkSqlEdit/index.tsx"],
4
- "sourcesContent": ["import {\n autocompletion,\n type Completion,\n type CompletionContext,\n type CompletionResult,\n} from '@codemirror/autocomplete';\nimport { MySQL, sql } from '@codemirror/lang-sql';\nimport { Decoration, type EditorView, ViewPlugin, type ViewUpdate } from '@codemirror/view';\nimport CodeMirror, { type ReactCodeMirrorRef } from '@uiw/react-codemirror';\nimport React from 'react';\nimport customStyles from './code-mirror-custom.module.less';\nimport { type SqlDialectType, sqlFunctions, sqlKeywords } from './sql-language';\n\nexport type YkSqlEditProps = {\n value: string;\n previewValue?: string;\n preview?: boolean;\n placeholder?: string;\n height?: string;\n width?: string;\n onChange: (value: string) => void;\n\n datasourceType?: SqlDialectType;\n keywordOptions?: {\n keywords: string[];\n functions: string[];\n };\n dataTestId?: string;\n};\n\n// 动态参数高亮插件\nfunction dynamicParamHighlighter() {\n return ViewPlugin.fromClass(\n class {\n decorations;\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n buildDecorations(view: EditorView) {\n const widgets = [];\n const regex = /\\{\\{.*?\\}\\}/g;\n for (const { from, to } of view.visibleRanges) {\n const text = view.state.doc.sliceString(from, to);\n let match;\n while ((match = regex.exec(text)) !== null) {\n const start = from + match.index;\n const end = start + match[0].length;\n widgets.push(Decoration.mark({ class: 'cm-dynamic-param' }).range(start, end));\n }\n }\n return Decoration.set(widgets, true);\n }\n },\n {\n decorations: (v) => v.decorations,\n },\n );\n}\n\nfunction customKeywordHighlighter(allKeywords: string[]) {\n return ViewPlugin.fromClass(\n class {\n decorations;\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n buildDecorations(view: EditorView) {\n if (!allKeywords.length) return Decoration.none;\n\n const widgets = [];\n const regex = new RegExp(`\\\\b(${allKeywords.join('|')})\\\\b`, 'gi');\n\n for (const { from, to } of view.visibleRanges) {\n const text = view.state.doc.sliceString(from, to);\n let match;\n while ((match = regex.exec(text)) !== null) {\n const start = from + match.index;\n const end = start + match[0].length;\n widgets.push(\n Decoration.mark({\n class: 'cm-custom-keyword',\n attributes: { 'data-keyword': match[0] },\n }).range(start, end),\n );\n }\n }\n return Decoration.set(widgets, true);\n }\n },\n {\n decorations: (v) => v.decorations,\n },\n );\n}\n\nfunction buildCompletions(keywordOptions?: YkSqlEditProps['keywordOptions']) {\n const keywords = keywordOptions?.keywords ?? [];\n const functions = keywordOptions?.functions ?? [];\n const allKeywords = [...new Set([...keywords, ...functions])];\n\n return (context: CompletionContext): CompletionResult | null => {\n const word = context.matchBefore(/\\w*/);\n if (word?.from === word?.to && !context.explicit) return null;\n\n const search = (word?.text ?? '').toLowerCase();\n const options: Completion[] = allKeywords\n .filter((kw) => kw.toLowerCase().includes(search))\n .map((kw) => ({\n label: kw,\n detail: keywords.includes(kw) ? '关键字' : functions.includes(kw) ? '函数' : '',\n boost: kw.toLowerCase().startsWith(search) ? 10 : 1,\n }))\n .sort((a, b) => (b.boost ?? 0) - (a.boost ?? 0));\n\n return {\n from: word?.from ?? 0,\n options: options.slice(0, 50),\n };\n };\n}\n\nconst YkSqlEdit = React.forwardRef<ReactCodeMirrorRef, YkSqlEditProps>((props, ref) => {\n const {\n value,\n previewValue,\n preview,\n placeholder = '请输入查询语句',\n height = '100%',\n width = '100%',\n onChange,\n datasourceType,\n keywordOptions,\n dataTestId = 'native-query-editor',\n } = props;\n\n const resolvedKeywordOptions = React.useMemo(() => {\n if (keywordOptions) return keywordOptions;\n if (!datasourceType) return { keywords: [], functions: [] };\n return {\n keywords: sqlKeywords(datasourceType),\n functions: sqlFunctions(datasourceType),\n };\n }, [datasourceType, keywordOptions]);\n\n const allKeywords = React.useMemo(() => {\n const keywords = resolvedKeywordOptions.keywords ?? [];\n const functions = resolvedKeywordOptions.functions ?? [];\n return [...new Set([...keywords, ...functions])];\n }, [resolvedKeywordOptions]);\n\n const customCompletions = React.useMemo(() => buildCompletions(resolvedKeywordOptions), [resolvedKeywordOptions]);\n\n return (\n <CodeMirror\n ref={ref}\n value={preview ? (previewValue ?? value) : value}\n className={`${customStyles.codeMirrorCustom} ${preview ? customStyles.disabled : ''}`}\n data-testid={dataTestId}\n placeholder={placeholder}\n height={height}\n width={width}\n editable={!preview}\n autoCorrect='off'\n extensions={[\n sql({ dialect: MySQL }),\n dynamicParamHighlighter(),\n customKeywordHighlighter(allKeywords),\n autocompletion({\n override: [customCompletions],\n }),\n ]}\n onChange={(next) => onChange(next)}\n basicSetup={{\n closeBrackets: true,\n autocompletion: true,\n bracketMatching: true,\n highlightSpecialChars: true,\n searchKeymap: true,\n history: true,\n historyKeymap: true,\n drawSelection: true,\n syntaxHighlighting: true,\n defaultKeymap: true,\n dropCursor: true,\n highlightSelectionMatches: true,\n completionKeymap: true,\n highlightActiveLineGutter: true,\n }}\n />\n );\n});\n\nYkSqlEdit.displayName = 'YkSqlEdit';\n\nexport default YkSqlEdit;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n autocompletion,\n type Completion,\n type CompletionContext,\n type CompletionResult,\n} from '@codemirror/autocomplete';\nimport { MySQL, sql } from '@codemirror/lang-sql';\nimport { Decoration, type EditorView, ViewPlugin, type ViewUpdate } from '@codemirror/view';\nimport CodeMirror, { type ReactCodeMirrorRef } from '@uiw/react-codemirror';\nimport React from 'react';\nimport customStyles from './code-mirror-custom.module.less';\nimport { type SqlDialectType, sqlFunctions, sqlKeywords } from './sql-language';\n\nexport type { SqlDialectType } from './sql-language';\n\nexport type YkSqlEditProps = {\n value: string;\n previewValue?: string;\n preview?: boolean;\n placeholder?: string;\n height?: string;\n width?: string;\n onChange: (value: string) => void;\n\n datasourceType?: SqlDialectType;\n keywordOptions?: {\n keywords: string[];\n functions: string[];\n };\n dataTestId?: string;\n};\n\n// 动态参数高亮插件\nfunction dynamicParamHighlighter() {\n return ViewPlugin.fromClass(\n class {\n decorations;\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n buildDecorations(view: EditorView) {\n const widgets = [];\n const regex = /\\{\\{.*?\\}\\}/g;\n for (const { from, to } of view.visibleRanges) {\n const text = view.state.doc.sliceString(from, to);\n let match;\n while ((match = regex.exec(text)) !== null) {\n const start = from + match.index;\n const end = start + match[0].length;\n widgets.push(Decoration.mark({ class: 'cm-dynamic-param' }).range(start, end));\n }\n }\n return Decoration.set(widgets, true);\n }\n },\n {\n decorations: (v) => v.decorations,\n },\n );\n}\n\nfunction customKeywordHighlighter(allKeywords: string[]) {\n return ViewPlugin.fromClass(\n class {\n decorations;\n constructor(view: EditorView) {\n this.decorations = this.buildDecorations(view);\n }\n update(update: ViewUpdate) {\n if (update.docChanged || update.viewportChanged) {\n this.decorations = this.buildDecorations(update.view);\n }\n }\n buildDecorations(view: EditorView) {\n if (!allKeywords.length) return Decoration.none;\n\n const widgets = [];\n const regex = new RegExp(`\\\\b(${allKeywords.join('|')})\\\\b`, 'gi');\n\n for (const { from, to } of view.visibleRanges) {\n const text = view.state.doc.sliceString(from, to);\n let match;\n while ((match = regex.exec(text)) !== null) {\n const start = from + match.index;\n const end = start + match[0].length;\n widgets.push(\n Decoration.mark({\n class: 'cm-custom-keyword',\n attributes: { 'data-keyword': match[0] },\n }).range(start, end),\n );\n }\n }\n return Decoration.set(widgets, true);\n }\n },\n {\n decorations: (v) => v.decorations,\n },\n );\n}\n\nfunction buildCompletions(keywordOptions?: YkSqlEditProps['keywordOptions']) {\n const keywords = keywordOptions?.keywords ?? [];\n const functions = keywordOptions?.functions ?? [];\n const allKeywords = [...new Set([...keywords, ...functions])];\n\n return (context: CompletionContext): CompletionResult | null => {\n const word = context.matchBefore(/\\w*/);\n if (word?.from === word?.to && !context.explicit) return null;\n\n const search = (word?.text ?? '').toLowerCase();\n const options: Completion[] = allKeywords\n .filter((kw) => kw.toLowerCase().includes(search))\n .map((kw) => ({\n label: kw,\n detail: keywords.includes(kw) ? '关键字' : functions.includes(kw) ? '函数' : '',\n boost: kw.toLowerCase().startsWith(search) ? 10 : 1,\n }))\n .sort((a, b) => (b.boost ?? 0) - (a.boost ?? 0));\n\n return {\n from: word?.from ?? 0,\n options: options.slice(0, 50),\n };\n };\n}\n\nconst YkSqlEdit = React.forwardRef<ReactCodeMirrorRef, YkSqlEditProps>((props, ref) => {\n const {\n value,\n previewValue,\n preview,\n placeholder = '请输入查询语句',\n height = '100%',\n width = '100%',\n onChange,\n datasourceType,\n keywordOptions,\n dataTestId = 'native-query-editor',\n } = props;\n\n const resolvedKeywordOptions = React.useMemo(() => {\n if (keywordOptions) return keywordOptions;\n if (!datasourceType) return { keywords: [], functions: [] };\n return {\n keywords: sqlKeywords(datasourceType),\n functions: sqlFunctions(datasourceType),\n };\n }, [datasourceType, keywordOptions]);\n\n const allKeywords = React.useMemo(() => {\n const keywords = resolvedKeywordOptions.keywords ?? [];\n const functions = resolvedKeywordOptions.functions ?? [];\n return [...new Set([...keywords, ...functions])];\n }, [resolvedKeywordOptions]);\n\n const customCompletions = React.useMemo(() => buildCompletions(resolvedKeywordOptions), [resolvedKeywordOptions]);\n\n return (\n <CodeMirror\n ref={ref}\n value={preview ? (previewValue ?? value) : value}\n className={`${customStyles.codeMirrorCustom} ${preview ? customStyles.disabled : ''}`}\n data-testid={dataTestId}\n placeholder={placeholder}\n height={height}\n width={width}\n editable={!preview}\n autoCorrect='off'\n extensions={[\n sql({ dialect: MySQL }),\n dynamicParamHighlighter(),\n customKeywordHighlighter(allKeywords),\n autocompletion({\n override: [customCompletions],\n }),\n ]}\n onChange={(next) => onChange(next)}\n basicSetup={{\n closeBrackets: true,\n autocompletion: true,\n bracketMatching: true,\n highlightSpecialChars: true,\n searchKeymap: true,\n history: true,\n historyKeymap: true,\n drawSelection: true,\n syntaxHighlighting: true,\n defaultKeymap: true,\n dropCursor: true,\n highlightSelectionMatches: true,\n completionKeymap: true,\n highlightActiveLineGutter: true,\n }}\n />\n );\n});\n\nYkSqlEdit.displayName = 'YkSqlEdit';\n\nexport default YkSqlEdit;\n"],
5
+ "mappings": "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",
6
6
  "names": ["_a", "_b"]
7
7
  }
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  /**
3
3
  * 倒计时时钟组件的 Props
4
4
  */
5
- type props = {
5
+ export type ClockProps = {
6
6
  /** 根节点类名,可选,用于样式覆盖 */
7
7
  className?: string;
8
8
  /** 秒数后的文案,默认「秒后更新数据」,展示为「{time} {text}」 */
@@ -15,5 +15,5 @@ type props = {
15
15
  /**
16
16
  * 倒计时时钟:展示距下一整分钟的剩余秒数,带环形进度条,剩 1 秒时调用 cellBack。
17
17
  */
18
- declare const Clock: React.FC<props>;
18
+ declare const Clock: React.FC<ClockProps>;
19
19
  export default Clock;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/Clock/index.tsx"],
4
- "sourcesContent": ["import classNames from 'classnames';\nimport React, { useEffect, useRef, useState } from 'react';\n\n/**\n * 倒计时时钟组件的 Props\n */\ntype props = {\n /** 根节点类名,可选,用于样式覆盖 */\n className?: string;\n /** 秒数后的文案,默认「秒后更新数据」,展示为「{time} {text}」 */\n text?: string;\n /** 是否隐藏文案,默认 false */\n hideText?: boolean;\n /** 剩余 1 秒时触发的回调,常用于刷新数据 */\n cellBack: () => void;\n};\n\n/**\n * 倒计时时钟:展示距下一整分钟的剩余秒数,带环形进度条,剩 1 秒时调用 cellBack。\n */\nconst Clock: React.FC<props> = ({ className, text = '秒后更新数据', hideText = false, cellBack }) => {\n /** 计算距下一整分钟的秒数:60 - 当前秒数 */\n const formatTime = (date: Date) => {\n return 60 - date.getSeconds();\n };\n\n /** 当前剩余秒数,每秒更新 */\n const [time, setTime] = useState(formatTime(new Date()));\n const cellBackRef = useRef(cellBack);\n\n /** 保证 interval 内始终调用到最新的 cellBack,避免闭包旧引用 */\n useEffect(() => {\n cellBackRef.current = cellBack;\n }, [cellBack]);\n\n /** 每秒更新剩余秒数,并在剩 1 秒时执行 cellBack */\n useEffect(() => {\n const timer = setInterval(() => {\n const newTime = formatTime(new Date());\n setTime(newTime);\n\n if (newTime === 1) {\n cellBackRef.current();\n }\n }, 1000);\n\n return () => {\n clearInterval(timer);\n };\n }, []);\n\n /** 进度条百分比(0~100),时间越少进度越少 */\n const progress = (time / 60) * 100;\n const radius = 16 / 2;\n const circumference = 2 * Math.PI * radius;\n\n return (\n <div\n className={classNames('op-clock', className)}\n style={{ display: 'flex', alignItems: 'baseline', marginLeft: 15 }}\n >\n <div className='op-clock-icon'>\n <svg style={{ width: 18, height: 18, transform: 'translateY(20%)' }}>\n <circle r={radius} cx='9' cy='9' stroke='#EDEFF4' strokeWidth='2' fill='transparent' />\n <circle\n r={radius}\n cx='9'\n cy='9'\n stroke='#65DAAA'\n strokeWidth='2'\n fill='transparent'\n strokeDasharray={circumference}\n strokeDashoffset={`${(circumference * (100 - progress)) / 100}`}\n transform='rotate(-90 9 9)'\n />\n </svg>\n </div>\n <div style={{ color: '#6b7981', fontSize: 12, marginLeft: 7 }}>{hideText ? '' : `${time} ${text}`}</div>\n </div>\n );\n};\n\nexport default Clock;\n"],
5
- "mappings": ";AAAA,OAAO,gBAAgB;AACvB,OAAO,SAAS,WAAW,QAAQ,gBAAgB;AAmBnD,IAAM,QAAyB,CAAC,EAAE,WAAW,OAAO,UAAU,WAAW,OAAO,SAAS,MAAM;AAE7F,QAAM,aAAa,CAAC,SAAe;AACjC,WAAO,KAAK,KAAK,WAAW;AAAA,EAC9B;AAGA,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,WAAW,oBAAI,KAAK,CAAC,CAAC;AACvD,QAAM,cAAc,OAAO,QAAQ;AAGnC,YAAU,MAAM;AACd,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACd,UAAM,QAAQ,YAAY,MAAM;AAC9B,YAAM,UAAU,WAAW,oBAAI,KAAK,CAAC;AACrC,cAAQ,OAAO;AAEf,UAAI,YAAY,GAAG;AACjB,oBAAY,QAAQ;AAAA,MACtB;AAAA,IACF,GAAG,GAAI;AAEP,WAAO,MAAM;AACX,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,WAAY,OAAO,KAAM;AAC/B,QAAM,SAAS,KAAK;AACpB,QAAM,gBAAgB,IAAI,KAAK,KAAK;AAEpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,WAAW,YAAY,SAAS;AAAA,MAC3C,OAAO,EAAE,SAAS,QAAQ,YAAY,YAAY,YAAY,GAAG;AAAA;AAAA,IAEjE,oCAAC,SAAI,WAAU,mBACb,oCAAC,SAAI,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,WAAW,kBAAkB,KAChE,oCAAC,YAAO,GAAG,QAAQ,IAAG,KAAI,IAAG,KAAI,QAAO,WAAU,aAAY,KAAI,MAAK,eAAc,GACrF;AAAA,MAAC;AAAA;AAAA,QACC,GAAG;AAAA,QACH,IAAG;AAAA,QACH,IAAG;AAAA,QACH,QAAO;AAAA,QACP,aAAY;AAAA,QACZ,MAAK;AAAA,QACL,iBAAiB;AAAA,QACjB,kBAAkB,GAAI,iBAAiB,MAAM,YAAa;AAAA,QAC1D,WAAU;AAAA;AAAA,IACZ,CACF,CACF;AAAA,IACA,oCAAC,SAAI,OAAO,EAAE,OAAO,WAAW,UAAU,IAAI,YAAY,EAAE,KAAI,WAAW,KAAK,GAAG,QAAQ,MAAO;AAAA,EACpG;AAEJ;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["import classNames from 'classnames';\nimport React, { useEffect, useRef, useState } from 'react';\n\n/**\n * 倒计时时钟组件的 Props\n */\nexport type ClockProps = {\n /** 根节点类名,可选,用于样式覆盖 */\n className?: string;\n /** 秒数后的文案,默认「秒后更新数据」,展示为「{time} {text}」 */\n text?: string;\n /** 是否隐藏文案,默认 false */\n hideText?: boolean;\n /** 剩余 1 秒时触发的回调,常用于刷新数据 */\n cellBack: () => void;\n};\n\n/**\n * 倒计时时钟:展示距下一整分钟的剩余秒数,带环形进度条,剩 1 秒时调用 cellBack。\n */\nconst Clock: React.FC<ClockProps> = ({ className, text = '秒后更新数据', hideText = false, cellBack }) => {\n /** 计算距下一整分钟的秒数:60 - 当前秒数 */\n const formatTime = (date: Date) => {\n return 60 - date.getSeconds();\n };\n\n /** 当前剩余秒数,每秒更新 */\n const [time, setTime] = useState(formatTime(new Date()));\n const cellBackRef = useRef(cellBack);\n\n /** 保证 interval 内始终调用到最新的 cellBack,避免闭包旧引用 */\n useEffect(() => {\n cellBackRef.current = cellBack;\n }, [cellBack]);\n\n /** 每秒更新剩余秒数,并在剩 1 秒时执行 cellBack */\n useEffect(() => {\n const timer = setInterval(() => {\n const newTime = formatTime(new Date());\n setTime(newTime);\n\n if (newTime === 1) {\n cellBackRef.current();\n }\n }, 1000);\n\n return () => {\n clearInterval(timer);\n };\n }, []);\n\n /** 进度条百分比(0~100),时间越少进度越少 */\n const progress = (time / 60) * 100;\n const radius = 16 / 2;\n const circumference = 2 * Math.PI * radius;\n\n return (\n <div\n className={classNames('op-clock', className)}\n style={{ display: 'flex', alignItems: 'baseline', marginLeft: 15 }}\n >\n <div className='op-clock-icon'>\n <svg style={{ width: 18, height: 18, transform: 'translateY(20%)' }}>\n <circle r={radius} cx='9' cy='9' stroke='#EDEFF4' strokeWidth='2' fill='transparent' />\n <circle\n r={radius}\n cx='9'\n cy='9'\n stroke='#65DAAA'\n strokeWidth='2'\n fill='transparent'\n strokeDasharray={circumference}\n strokeDashoffset={`${(circumference * (100 - progress)) / 100}`}\n transform='rotate(-90 9 9)'\n />\n </svg>\n </div>\n <div style={{ color: '#6b7981', fontSize: 12, marginLeft: 7 }}>{hideText ? '' : `${time} ${text}`}</div>\n </div>\n );\n};\n\nexport default Clock;\n"],
5
+ "mappings": ";AAAA,OAAO,gBAAgB;AACvB,OAAO,SAAS,WAAW,QAAQ,gBAAgB;AAmBnD,IAAM,QAA8B,CAAC,EAAE,WAAW,OAAO,UAAU,WAAW,OAAO,SAAS,MAAM;AAElG,QAAM,aAAa,CAAC,SAAe;AACjC,WAAO,KAAK,KAAK,WAAW;AAAA,EAC9B;AAGA,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,WAAW,oBAAI,KAAK,CAAC,CAAC;AACvD,QAAM,cAAc,OAAO,QAAQ;AAGnC,YAAU,MAAM;AACd,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,QAAQ,CAAC;AAGb,YAAU,MAAM;AACd,UAAM,QAAQ,YAAY,MAAM;AAC9B,YAAM,UAAU,WAAW,oBAAI,KAAK,CAAC;AACrC,cAAQ,OAAO;AAEf,UAAI,YAAY,GAAG;AACjB,oBAAY,QAAQ;AAAA,MACtB;AAAA,IACF,GAAG,GAAI;AAEP,WAAO,MAAM;AACX,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,WAAY,OAAO,KAAM;AAC/B,QAAM,SAAS,KAAK;AACpB,QAAM,gBAAgB,IAAI,KAAK,KAAK;AAEpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,WAAW,YAAY,SAAS;AAAA,MAC3C,OAAO,EAAE,SAAS,QAAQ,YAAY,YAAY,YAAY,GAAG;AAAA;AAAA,IAEjE,oCAAC,SAAI,WAAU,mBACb,oCAAC,SAAI,OAAO,EAAE,OAAO,IAAI,QAAQ,IAAI,WAAW,kBAAkB,KAChE,oCAAC,YAAO,GAAG,QAAQ,IAAG,KAAI,IAAG,KAAI,QAAO,WAAU,aAAY,KAAI,MAAK,eAAc,GACrF;AAAA,MAAC;AAAA;AAAA,QACC,GAAG;AAAA,QACH,IAAG;AAAA,QACH,IAAG;AAAA,QACH,QAAO;AAAA,QACP,aAAY;AAAA,QACZ,MAAK;AAAA,QACL,iBAAiB;AAAA,QACjB,kBAAkB,GAAI,iBAAiB,MAAM,YAAa;AAAA,QAC1D,WAAU;AAAA;AAAA,IACZ,CACF,CACF;AAAA,IACA,oCAAC,SAAI,OAAO,EAAE,OAAO,WAAW,UAAU,IAAI,YAAY,EAAE,KAAI,WAAW,KAAK,GAAG,QAAQ,MAAO;AAAA,EACpG;AAEJ;AAEA,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- type PropsType = {
2
+ export type DebounceInputProps = {
3
3
  noDebounced?: boolean;
4
4
  currentValue: string | undefined;
5
5
  placeholder?: string;
@@ -12,5 +12,5 @@ type PropsType = {
12
12
  disabled?: boolean;
13
13
  icon?: React.ReactNode;
14
14
  };
15
- declare const DebouncedInput: React.FC<PropsType>;
15
+ declare const DebouncedInput: React.FC<DebounceInputProps>;
16
16
  export default DebouncedInput;