@lobehub/ui 5.49.0 → 5.50.0

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 (78) hide show
  1. package/es/Empty/Empty.d.mts +1 -2
  2. package/es/Empty/Empty.mjs +107 -53
  3. package/es/Empty/Empty.mjs.map +1 -1
  4. package/es/Empty/style.mjs +48 -0
  5. package/es/Empty/style.mjs.map +1 -0
  6. package/es/Empty/type.d.mts +7 -8
  7. package/es/HtmlPreview/HtmlPreview.mjs +5 -2
  8. package/es/HtmlPreview/HtmlPreview.mjs.map +1 -1
  9. package/es/Markdown/type.d.mts +1 -0
  10. package/es/base-ui/Badge/Badge.d.mts +6 -0
  11. package/es/base-ui/Badge/Badge.mjs +73 -0
  12. package/es/base-ui/Badge/Badge.mjs.map +1 -0
  13. package/es/base-ui/Badge/index.d.mts +3 -0
  14. package/es/base-ui/Badge/style.mjs +112 -0
  15. package/es/base-ui/Badge/style.mjs.map +1 -0
  16. package/es/base-ui/Badge/type.d.mts +19 -0
  17. package/es/base-ui/Input/style.d.mts +1 -1
  18. package/es/base-ui/Pagination/Pagination.d.mts +6 -0
  19. package/es/base-ui/Pagination/Pagination.mjs +123 -0
  20. package/es/base-ui/Pagination/Pagination.mjs.map +1 -0
  21. package/es/base-ui/Pagination/helpers.mjs +18 -0
  22. package/es/base-ui/Pagination/helpers.mjs.map +1 -0
  23. package/es/base-ui/Pagination/index.d.mts +3 -0
  24. package/es/base-ui/Pagination/style.mjs +92 -0
  25. package/es/base-ui/Pagination/style.mjs.map +1 -0
  26. package/es/base-ui/Pagination/type.d.mts +22 -0
  27. package/es/base-ui/Progress/Progress.d.mts +6 -0
  28. package/es/base-ui/Progress/Progress.mjs +179 -0
  29. package/es/base-ui/Progress/Progress.mjs.map +1 -0
  30. package/es/base-ui/Progress/index.d.mts +3 -0
  31. package/es/base-ui/Progress/style.mjs +203 -0
  32. package/es/base-ui/Progress/style.mjs.map +1 -0
  33. package/es/base-ui/Progress/type.d.mts +24 -0
  34. package/es/base-ui/Result/Result.d.mts +6 -0
  35. package/es/base-ui/Result/Result.mjs +69 -0
  36. package/es/base-ui/Result/Result.mjs.map +1 -0
  37. package/es/base-ui/Result/index.d.mts +3 -0
  38. package/es/base-ui/Result/style.mjs +55 -0
  39. package/es/base-ui/Result/style.mjs.map +1 -0
  40. package/es/base-ui/Result/type.d.mts +14 -0
  41. package/es/base-ui/Spin/NetworkGlyph.mjs +70 -0
  42. package/es/base-ui/Spin/NetworkGlyph.mjs.map +1 -0
  43. package/es/base-ui/Spin/Spin.d.mts +6 -0
  44. package/es/base-ui/Spin/Spin.mjs +100 -0
  45. package/es/base-ui/Spin/Spin.mjs.map +1 -0
  46. package/es/base-ui/Spin/index.d.mts +3 -0
  47. package/es/base-ui/Spin/style.mjs +166 -0
  48. package/es/base-ui/Spin/style.mjs.map +1 -0
  49. package/es/base-ui/Spin/type.d.mts +18 -0
  50. package/es/base-ui/Upload/Upload.d.mts +6 -0
  51. package/es/base-ui/Upload/Upload.mjs +148 -0
  52. package/es/base-ui/Upload/Upload.mjs.map +1 -0
  53. package/es/base-ui/Upload/UploadDragger.d.mts +6 -0
  54. package/es/base-ui/Upload/UploadDragger.mjs +14 -0
  55. package/es/base-ui/Upload/UploadDragger.mjs.map +1 -0
  56. package/es/base-ui/Upload/helpers.mjs +17 -0
  57. package/es/base-ui/Upload/helpers.mjs.map +1 -0
  58. package/es/base-ui/Upload/index.d.mts +4 -0
  59. package/es/base-ui/Upload/style.mjs +74 -0
  60. package/es/base-ui/Upload/style.mjs.map +1 -0
  61. package/es/base-ui/Upload/type.d.mts +24 -0
  62. package/es/base-ui/index.d.mts +20 -1
  63. package/es/base-ui/index.mjs +10 -3
  64. package/es/hooks/useMarkdown/useMarkdownRehypePlugins.mjs +2 -0
  65. package/es/hooks/useMarkdown/useMarkdownRehypePlugins.mjs.map +1 -1
  66. package/es/index.d.mts +20 -4
  67. package/es/index.mjs +8 -2
  68. package/es/static-css/baseline.mjs +0 -1
  69. package/es/static-css/baseline.mjs.map +1 -1
  70. package/package.json +2 -1
  71. package/es/NeuralNetworkLoading/NeuralNetworkLoading.d.mts +0 -6
  72. package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs +0 -142
  73. package/es/NeuralNetworkLoading/NeuralNetworkLoading.mjs.map +0 -1
  74. package/es/NeuralNetworkLoading/index.d.mts +0 -3
  75. package/es/NeuralNetworkLoading/index.d.ts +0 -1
  76. package/es/NeuralNetworkLoading/index.js +0 -1
  77. package/es/NeuralNetworkLoading/index.mjs +0 -2
  78. package/es/NeuralNetworkLoading/type.d.mts +0 -11
@@ -1,7 +1,6 @@
1
1
  import { EmptyProps } from "./type.mjs";
2
- import { FC } from "react";
3
2
  //#region src/Empty/Empty.d.ts
4
- declare const Empty: FC<EmptyProps>;
3
+ declare const Empty: import("react").NamedExoticComponent<EmptyProps>;
5
4
  //#endregion
6
5
  export { Empty as default };
7
6
  //# sourceMappingURL=Empty.d.mts.map
@@ -1,76 +1,130 @@
1
1
  "use client";
2
- import FlexBasic_default from "../Flex/FlexBasic.mjs";
3
- import Block from "../Block/Block.mjs";
4
2
  import Icon from "../Icon/Icon.mjs";
5
3
  import Text from "../Text/Text.mjs";
6
4
  import FluentEmoji from "../FluentEmoji/FluentEmoji.mjs";
5
+ import { styles } from "./style.mjs";
6
+ import { memo, useMemo } from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
- import { Empty } from "antd";
9
- import { cssVar, useThemeMode } from "antd-style";
8
+ import { cssVar, cx } from "antd-style";
9
+ import { Plus } from "lucide-react";
10
10
  //#region src/Empty/Empty.tsx
11
- const Empty$1 = ({ title, description, icon, image, emoji, imageSize = 48, iconColor, action, children, imageProps, align, actionProps, type = "default", titleProps, descriptionProps, ...rest }) => {
12
- const { isDarkMode } = useThemeMode();
11
+ const Empty = memo(({ title, description, icon, iconColor, emoji, image, imageSize = 48, action, actionProps, titleProps, descriptionProps, align, imageProps, children, type = "default", variant = "default", className, onClick, ref, style, ...rest }) => {
13
12
  const isPage = type === "page";
14
13
  const alignValue = align || (isPage ? "flex-start" : "center");
15
14
  const isCenter = alignValue === "center";
16
- const fallbackImage = Empty.PRESENTED_IMAGE_SIMPLE;
17
- const cover = image || emoji || icon ? image ? image : /* @__PURE__ */ jsxs(Block, {
18
- align: "center",
19
- flex: "none",
20
- height: imageSize,
21
- justify: "center",
22
- variant: "outlined",
23
- width: imageSize,
24
- ...imageProps,
25
- style: {
26
- marginBottom: 4,
27
- ...imageProps?.style
28
- },
29
- children: [icon && /* @__PURE__ */ jsx(Icon, {
30
- icon,
31
- size: imageSize * .66,
32
- color: iconColor || (isDarkMode ? cssVar.colorTextQuaternary : cssVar.colorTextSecondary)
33
- }), emoji && /* @__PURE__ */ jsx(FluentEmoji, {
15
+ const isClickable = !isPage && variant === "dashed" && !!onClick;
16
+ const resolvedIcon = icon ?? (isClickable ? Plus : void 0);
17
+ const iconSize = isPage ? 36 : variant === "dashed" ? 20 : 32;
18
+ const cover = useMemo(() => {
19
+ if (image) return image;
20
+ if (emoji) return /* @__PURE__ */ jsx(FluentEmoji, {
34
21
  emoji,
35
- size: imageSize * .75,
22
+ size: imageSize,
36
23
  type: "anim"
37
- })]
38
- }) : fallbackImage;
39
- return /* @__PURE__ */ jsxs(FlexBasic_default, {
40
- align: alignValue,
41
- gap: 8,
42
- padding: 16,
24
+ });
25
+ if (!resolvedIcon) return null;
26
+ return /* @__PURE__ */ jsx(Icon, {
27
+ color: iconColor,
28
+ icon: resolvedIcon,
29
+ size: {
30
+ size: iconSize,
31
+ strokeWidth: isPage ? 1.25 : 2
32
+ }
33
+ });
34
+ }, [
35
+ image,
36
+ emoji,
37
+ imageSize,
38
+ resolvedIcon,
39
+ isPage,
40
+ iconColor,
41
+ iconSize
42
+ ]);
43
+ const rootClassName = cx(isPage ? styles.rootPage : styles.root, !isPage && variant === "dashed" && styles.dashed, isClickable && styles.dashedClickable, className);
44
+ const handleKeyDown = (event) => {
45
+ if (!isClickable) return;
46
+ if (event.key !== "Enter" && event.key !== " ") return;
47
+ event.preventDefault();
48
+ onClick?.(event);
49
+ };
50
+ const rootStyle = {
51
+ color: !isPage && variant === "dashed" ? cssVar.colorTextTertiary : cssVar.colorTextQuaternary,
52
+ ...style
53
+ };
54
+ const titleNode = title && /* @__PURE__ */ jsx(Text, {
55
+ align: isCenter ? "center" : void 0,
56
+ color: cssVar.colorText,
57
+ fontSize: isPage ? 18 : 14,
58
+ weight: isPage ? 600 : 500,
59
+ style: {
60
+ marginBottom: isPage ? 4 : 0,
61
+ marginTop: isPage ? 0 : variant === "dashed" ? 6 : 8
62
+ },
63
+ ...titleProps,
64
+ children: title
65
+ });
66
+ const descriptionNode = description && /* @__PURE__ */ jsx(Text, {
67
+ align: isCenter ? "center" : void 0,
68
+ color: cssVar.colorTextTertiary,
69
+ fontSize: 13,
70
+ style: { maxWidth: isPage ? "52ch" : "34ch" },
71
+ ...descriptionProps,
72
+ children: description
73
+ });
74
+ if (isPage) return /* @__PURE__ */ jsxs("div", {
75
+ className: rootClassName,
76
+ ref,
77
+ style: {
78
+ alignItems: alignValue,
79
+ ...rootStyle
80
+ },
81
+ onClick,
82
+ ...rest,
83
+ children: [cover && /* @__PURE__ */ jsx("div", {
84
+ ...imageProps,
85
+ children: cover
86
+ }), /* @__PURE__ */ jsxs("div", { children: [
87
+ titleNode,
88
+ descriptionNode,
89
+ children,
90
+ action && /* @__PURE__ */ jsx("div", {
91
+ className: styles.extraPage,
92
+ ...actionProps,
93
+ children: action
94
+ })
95
+ ] })]
96
+ });
97
+ return /* @__PURE__ */ jsxs("div", {
98
+ className: rootClassName,
99
+ ref,
100
+ role: isClickable ? "button" : void 0,
101
+ style: {
102
+ alignItems: alignValue,
103
+ textAlign: isCenter ? "center" : void 0,
104
+ ...rootStyle
105
+ },
106
+ tabIndex: isClickable ? 0 : void 0,
107
+ onClick,
108
+ onKeyDown: handleKeyDown,
43
109
  ...rest,
44
110
  children: [
45
- cover,
46
- /* @__PURE__ */ jsxs(FlexBasic_default, {
47
- align: alignValue,
48
- gap: isPage ? 4 : 1,
49
- children: [title && /* @__PURE__ */ jsx(Text, {
50
- align: isCenter ? "center" : void 0,
51
- fontSize: isPage ? 24 : 16,
52
- weight: "bold",
53
- ...titleProps,
54
- children: title
55
- }), description && /* @__PURE__ */ jsx(Text, {
56
- align: isCenter ? "center" : void 0,
57
- color: isPage ? cssVar.colorTextSecondary : cssVar.colorTextDescription,
58
- fontSize: isPage ? 16 : 14,
59
- ...descriptionProps,
60
- children: description
61
- })]
111
+ cover && /* @__PURE__ */ jsx("div", {
112
+ ...imageProps,
113
+ children: cover
62
114
  }),
115
+ titleNode,
116
+ descriptionNode,
63
117
  children,
64
- action && /* @__PURE__ */ jsx(FlexBasic_default, {
65
- gap: 4,
118
+ action && /* @__PURE__ */ jsx("div", {
119
+ className: styles.action,
66
120
  ...actionProps,
67
121
  children: action
68
122
  })
69
123
  ]
70
124
  });
71
- };
72
- Empty$1.displayName = "Empty";
125
+ });
126
+ Empty.displayName = "Empty";
73
127
  //#endregion
74
- export { Empty$1 as default };
128
+ export { Empty as default };
75
129
 
76
130
  //# sourceMappingURL=Empty.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Empty.mjs","names":["Empty","AntEmpty","Flexbox"],"sources":["../../src/Empty/Empty.tsx"],"sourcesContent":["'use client';\n\nimport { Empty as AntEmpty } from 'antd';\nimport { cssVar, useThemeMode } from 'antd-style';\nimport { type FC } from 'react';\n\nimport Block from '@/Block';\nimport { Flexbox } from '@/Flex';\nimport FluentEmoji from '@/FluentEmoji';\nimport Icon from '@/Icon';\nimport Text from '@/Text';\n\nimport type { EmptyProps } from './type';\n\nconst Empty: FC<EmptyProps> = ({\n title,\n description,\n icon,\n image,\n emoji,\n imageSize = 48,\n iconColor,\n action,\n children,\n imageProps,\n align,\n actionProps,\n type = 'default',\n titleProps,\n descriptionProps,\n ...rest\n}) => {\n const { isDarkMode } = useThemeMode();\n const isPage = type === 'page';\n const alignValue = align || (isPage ? 'flex-start' : 'center');\n const isCenter = alignValue === 'center';\n\n const fallbackImage = AntEmpty.PRESENTED_IMAGE_SIMPLE;\n const hasImage = image || emoji || icon;\n const cover = hasImage ? (\n image ? (\n image\n ) : (\n <Block\n align={'center'}\n flex={'none'}\n height={imageSize}\n justify=\"center\"\n variant={'outlined'}\n width={imageSize}\n {...imageProps}\n style={{\n marginBottom: 4,\n ...imageProps?.style,\n }}\n >\n {icon && (\n <Icon\n icon={icon}\n size={imageSize * 0.66}\n color={\n iconColor || (isDarkMode ? cssVar.colorTextQuaternary : cssVar.colorTextSecondary)\n }\n />\n )}\n {emoji && <FluentEmoji emoji={emoji} size={imageSize * 0.75} type={'anim'} />}\n </Block>\n )\n ) : (\n fallbackImage\n );\n\n return (\n <Flexbox align={alignValue} gap={8} padding={16} {...rest}>\n {cover}\n <Flexbox align={alignValue} gap={isPage ? 4 : 1}>\n {title && (\n <Text\n align={isCenter ? 'center' : undefined}\n fontSize={isPage ? 24 : 16}\n weight={'bold'}\n {...titleProps}\n >\n {title}\n </Text>\n )}\n {description && (\n <Text\n align={isCenter ? 'center' : undefined}\n color={isPage ? cssVar.colorTextSecondary : cssVar.colorTextDescription}\n fontSize={isPage ? 16 : 14}\n {...descriptionProps}\n >\n {description}\n </Text>\n )}\n </Flexbox>\n {children}\n {action && (\n <Flexbox gap={4} {...actionProps}>\n {action}\n </Flexbox>\n )}\n </Flexbox>\n );\n};\n\nEmpty.displayName = 'Empty';\n\nexport default Empty;\n"],"mappings":";;;;;;;;;;AAcA,MAAMA,WAAyB,EAC7B,OACA,aACA,MACA,OACA,OACA,YAAY,IACZ,WACA,QACA,UACA,YACA,OACA,aACA,OAAO,WACP,YACA,kBACA,GAAG,WACC;CACJ,MAAM,EAAE,eAAe,aAAa;CACpC,MAAM,SAAS,SAAS;CACxB,MAAM,aAAa,UAAU,SAAS,eAAe;CACrD,MAAM,WAAW,eAAe;CAEhC,MAAM,gBAAgBC,MAAS;CAE/B,MAAM,QADW,SAAS,SAAS,OAEjC,QACE,QAEA,qBAAC,OAAD;EACE,OAAO;EACP,MAAM;EACN,QAAQ;EACR,SAAQ;EACR,SAAS;EACT,OAAO;EACP,GAAI;EACJ,OAAO;GACL,cAAc;GACd,GAAG,YAAY;EACjB;EAXF,UAAA,CAaG,QACC,oBAAC,MAAD;GACQ;GACN,MAAM,YAAY;GAClB,OACE,cAAc,aAAa,OAAO,sBAAsB,OAAO;EAElE,CAAA,GAEF,SAAS,oBAAC,aAAD;GAAoB;GAAO,MAAM,YAAY;GAAM,MAAM;EAAS,CAAA,CACvE;CAGT,CAAA,IAAA;CAGF,OACE,qBAACC,mBAAD;EAAS,OAAO;EAAY,KAAK;EAAG,SAAS;EAAI,GAAI;EAArD,UAAA;GACG;GACD,qBAACA,mBAAD;IAAS,OAAO;IAAY,KAAK,SAAS,IAAI;IAA9C,UAAA,CACG,SACC,oBAAC,MAAD;KACE,OAAO,WAAW,WAAW,KAAA;KAC7B,UAAU,SAAS,KAAK;KACxB,QAAQ;KACR,GAAI;KAEH,UAAA;IACG,CAAA,GAEP,eACC,oBAAC,MAAD;KACE,OAAO,WAAW,WAAW,KAAA;KAC7B,OAAO,SAAS,OAAO,qBAAqB,OAAO;KACnD,UAAU,SAAS,KAAK;KACxB,GAAI;KAEH,UAAA;IACG,CAAA,CAED;;GACR;GACA,UACC,oBAACA,mBAAD;IAAS,KAAK;IAAG,GAAI;IAClB,UAAA;GACM,CAAA;EAEJ;;AAEb;AAEA,QAAM,cAAc"}
1
+ {"version":3,"file":"Empty.mjs","names":[],"sources":["../../src/Empty/Empty.tsx"],"sourcesContent":["'use client';\n\nimport { cssVar, cx } from 'antd-style';\nimport { Plus } from 'lucide-react';\nimport { type KeyboardEvent, memo, useMemo } from 'react';\n\nimport FluentEmoji from '@/FluentEmoji';\nimport Icon from '@/Icon';\nimport Text from '@/Text';\n\nimport { styles } from './style';\nimport type { EmptyProps } from './type';\n\nconst Empty = memo<EmptyProps>(\n ({\n title,\n description,\n icon,\n iconColor,\n emoji,\n image,\n imageSize = 48,\n action,\n actionProps,\n titleProps,\n descriptionProps,\n align,\n imageProps,\n children,\n type = 'default',\n variant = 'default',\n className,\n onClick,\n ref,\n style,\n ...rest\n }) => {\n const isPage = type === 'page';\n const alignValue = align || (isPage ? 'flex-start' : 'center');\n const isCenter = alignValue === 'center';\n\n const isClickable = !isPage && variant === 'dashed' && !!onClick;\n const resolvedIcon = icon ?? (isClickable ? Plus : undefined);\n\n const iconSize = isPage ? 36 : variant === 'dashed' ? 20 : 32;\n\n const cover = useMemo(() => {\n if (image) return image;\n if (emoji) return <FluentEmoji emoji={emoji} size={imageSize} type={'anim'} />;\n if (!resolvedIcon) return null;\n\n return (\n <Icon\n color={iconColor}\n icon={resolvedIcon}\n size={{ size: iconSize, strokeWidth: isPage ? 1.25 : 2 }}\n />\n );\n }, [image, emoji, imageSize, resolvedIcon, isPage, iconColor, iconSize]);\n\n const rootClassName = cx(\n isPage ? styles.rootPage : styles.root,\n !isPage && variant === 'dashed' && styles.dashed,\n isClickable && styles.dashedClickable,\n className,\n );\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n if (!isClickable) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n\n event.preventDefault();\n (onClick as (event: unknown) => void)?.(event);\n };\n\n const rootStyle: EmptyProps['style'] = {\n color:\n !isPage && variant === 'dashed' ? cssVar.colorTextTertiary : cssVar.colorTextQuaternary,\n ...style,\n };\n\n const titleNode = title && (\n <Text\n align={isCenter ? 'center' : undefined}\n color={cssVar.colorText}\n fontSize={isPage ? 18 : 14}\n weight={isPage ? 600 : 500}\n style={{\n marginBottom: isPage ? 4 : 0,\n marginTop: isPage ? 0 : variant === 'dashed' ? 6 : 8,\n }}\n {...titleProps}\n >\n {title}\n </Text>\n );\n\n const descriptionNode = description && (\n <Text\n align={isCenter ? 'center' : undefined}\n color={cssVar.colorTextTertiary}\n fontSize={13}\n style={{ maxWidth: isPage ? '52ch' : '34ch' }}\n {...descriptionProps}\n >\n {description}\n </Text>\n );\n\n if (isPage) {\n return (\n <div\n className={rootClassName}\n ref={ref}\n style={{ alignItems: alignValue, ...rootStyle }}\n onClick={onClick}\n {...rest}\n >\n {cover && <div {...imageProps}>{cover}</div>}\n <div>\n {titleNode}\n {descriptionNode}\n {children}\n {action && (\n <div className={styles.extraPage} {...actionProps}>\n {action}\n </div>\n )}\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={rootClassName}\n ref={ref}\n role={isClickable ? 'button' : undefined}\n style={{ alignItems: alignValue, textAlign: isCenter ? 'center' : undefined, ...rootStyle }}\n tabIndex={isClickable ? 0 : undefined}\n onClick={onClick}\n onKeyDown={handleKeyDown}\n {...rest}\n >\n {cover && <div {...imageProps}>{cover}</div>}\n {titleNode}\n {descriptionNode}\n {children}\n {action && (\n <div className={styles.action} {...actionProps}>\n {action}\n </div>\n )}\n </div>\n );\n },\n);\n\nEmpty.displayName = 'Empty';\n\nexport default Empty;\n"],"mappings":";;;;;;;;;;AAaA,MAAM,QAAQ,MACX,EACC,OACA,aACA,MACA,WACA,OACA,OACA,YAAY,IACZ,QACA,aACA,YACA,kBACA,OACA,YACA,UACA,OAAO,WACP,UAAU,WACV,WACA,SACA,KACA,OACA,GAAG,WACC;CACJ,MAAM,SAAS,SAAS;CACxB,MAAM,aAAa,UAAU,SAAS,eAAe;CACrD,MAAM,WAAW,eAAe;CAEhC,MAAM,cAAc,CAAC,UAAU,YAAY,YAAY,CAAC,CAAC;CACzD,MAAM,eAAe,SAAS,cAAc,OAAO,KAAA;CAEnD,MAAM,WAAW,SAAS,KAAK,YAAY,WAAW,KAAK;CAE3D,MAAM,QAAQ,cAAc;EAC1B,IAAI,OAAO,OAAO;EAClB,IAAI,OAAO,OAAO,oBAAC,aAAD;GAAoB;GAAO,MAAM;GAAW,MAAM;EAAS,CAAA;EAC7E,IAAI,CAAC,cAAc,OAAO;EAE1B,OACE,oBAAC,MAAD;GACE,OAAO;GACP,MAAM;GACN,MAAM;IAAE,MAAM;IAAU,aAAa,SAAS,OAAO;GAAE;EACxD,CAAA;CAEL,GAAG;EAAC;EAAO;EAAO;EAAW;EAAc;EAAQ;EAAW;CAAQ,CAAC;CAEvE,MAAM,gBAAgB,GACpB,SAAS,OAAO,WAAW,OAAO,MAClC,CAAC,UAAU,YAAY,YAAY,OAAO,QAC1C,eAAe,OAAO,iBACtB,SACF;CAEA,MAAM,iBAAiB,UAAyC;EAC9D,IAAI,CAAC,aAAa;EAClB,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;EAEhD,MAAM,eAAe;EACrB,UAAwC,KAAK;CAC/C;CAEA,MAAM,YAAiC;EACrC,OACE,CAAC,UAAU,YAAY,WAAW,OAAO,oBAAoB,OAAO;EACtE,GAAG;CACL;CAEA,MAAM,YAAY,SAChB,oBAAC,MAAD;EACE,OAAO,WAAW,WAAW,KAAA;EAC7B,OAAO,OAAO;EACd,UAAU,SAAS,KAAK;EACxB,QAAQ,SAAS,MAAM;EACvB,OAAO;GACL,cAAc,SAAS,IAAI;GAC3B,WAAW,SAAS,IAAI,YAAY,WAAW,IAAI;EACrD;EACA,GAAI;EAEH,UAAA;CACG,CAAA;CAGR,MAAM,kBAAkB,eACtB,oBAAC,MAAD;EACE,OAAO,WAAW,WAAW,KAAA;EAC7B,OAAO,OAAO;EACd,UAAU;EACV,OAAO,EAAE,UAAU,SAAS,SAAS,OAAO;EAC5C,GAAI;EAEH,UAAA;CACG,CAAA;CAGR,IAAI,QACF,OACE,qBAAC,OAAD;EACE,WAAW;EACN;EACL,OAAO;GAAE,YAAY;GAAY,GAAG;EAAU;EACrC;EACT,GAAI;EALN,UAAA,CAOG,SAAS,oBAAC,OAAD;GAAK,GAAI;GAAa,UAAA;EAAW,CAAA,GAC3C,qBAAC,OAAD,EAAA,UAAA;GACG;GACA;GACA;GACA,UACC,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAW,GAAI;IACnC,UAAA;GACE,CAAA;EAEJ,EAAA,CAAA,CACF;;CAIT,OACE,qBAAC,OAAD;EACE,WAAW;EACN;EACL,MAAM,cAAc,WAAW,KAAA;EAC/B,OAAO;GAAE,YAAY;GAAY,WAAW,WAAW,WAAW,KAAA;GAAW,GAAG;EAAU;EAC1F,UAAU,cAAc,IAAI,KAAA;EACnB;EACT,WAAW;EACX,GAAI;EARN,UAAA;GAUG,SAAS,oBAAC,OAAD;IAAK,GAAI;IAAa,UAAA;GAAW,CAAA;GAC1C;GACA;GACA;GACA,UACC,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAQ,GAAI;IAChC,UAAA;GACE,CAAA;EAEJ;;AAET,CACF;AAEA,MAAM,cAAc"}
@@ -0,0 +1,48 @@
1
+ import { createStaticStyles } from "antd-style";
2
+ //#region src/Empty/style.ts
3
+ const styles = createStaticStyles(({ css, cssVar }) => ({
4
+ action: css`
5
+ margin-block-start: 8px;
6
+ `,
7
+ dashed: css`
8
+ padding-block: 24px;
9
+ padding-inline: 16px;
10
+ border: 1px dashed ${cssVar.colorBorder};
11
+ border-radius: ${cssVar.borderRadiusLG};
12
+ `,
13
+ dashedClickable: css`
14
+ cursor: pointer;
15
+ transition:
16
+ border-color 0.15s,
17
+ background 0.15s;
18
+
19
+ &:hover {
20
+ border-color: ${cssVar.colorTextTertiary};
21
+ background: ${cssVar.colorFillQuaternary};
22
+ }
23
+ `,
24
+ extraPage: css`
25
+ display: flex;
26
+ gap: 8px;
27
+ margin-block-start: 14px;
28
+ `,
29
+ root: css`
30
+ display: flex;
31
+ flex-direction: column;
32
+ gap: 4px;
33
+ align-items: center;
34
+
35
+ padding-block: 16px;
36
+ padding-inline: 8px;
37
+ `,
38
+ rootPage: css`
39
+ display: flex;
40
+ gap: 20px;
41
+ align-items: flex-start;
42
+ padding: 8px;
43
+ `
44
+ }));
45
+ //#endregion
46
+ export { styles };
47
+
48
+ //# sourceMappingURL=style.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.mjs","names":[],"sources":["../../src/Empty/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n action: css`\n margin-block-start: 8px;\n `,\n dashed: css`\n padding-block: 24px;\n padding-inline: 16px;\n border: 1px dashed ${cssVar.colorBorder};\n border-radius: ${cssVar.borderRadiusLG};\n `,\n dashedClickable: css`\n cursor: pointer;\n transition:\n border-color 0.15s,\n background 0.15s;\n\n &:hover {\n border-color: ${cssVar.colorTextTertiary};\n background: ${cssVar.colorFillQuaternary};\n }\n `,\n extraPage: css`\n display: flex;\n gap: 8px;\n margin-block-start: 14px;\n `,\n root: css`\n display: flex;\n flex-direction: column;\n gap: 4px;\n align-items: center;\n\n padding-block: 16px;\n padding-inline: 8px;\n `,\n rootPage: css`\n display: flex;\n gap: 20px;\n align-items: flex-start;\n padding: 8px;\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;;;CAGX,QAAQ,GAAG;;;yBAGY,OAAO,YAAY;qBACvB,OAAO,eAAe;;CAEzC,iBAAiB,GAAG;;;;;;;sBAOA,OAAO,kBAAkB;oBAC3B,OAAO,oBAAoB;;;CAG7C,WAAW,GAAG;;;;;CAKd,MAAM,GAAG;;;;;;;;;CAST,UAAU,GAAG;;;;;;AAMf,EAAE"}
@@ -1,27 +1,26 @@
1
- import { FlexboxProps } from "../Flex/type.mjs";
2
- import "../Flex/index.mjs";
3
- import { BlockProps } from "../Block/type.mjs";
4
- import "../Block/index.mjs";
5
1
  import { IconProps } from "../Icon/type.mjs";
6
2
  import "../Icon/index.mjs";
7
3
  import { TextProps } from "../Text/type.mjs";
8
4
  import "../Text/index.mjs";
9
- import { ReactNode } from "react";
5
+ import { CSSProperties, ComponentProps, ReactNode, Ref } from "react";
10
6
  //#region src/Empty/type.d.ts
11
- interface EmptyProps extends Omit<FlexboxProps, 'title'> {
7
+ interface EmptyProps extends Omit<ComponentProps<'div'>, 'title'> {
12
8
  action?: ReactNode;
13
- actionProps?: Omit<FlexboxProps, 'children'>;
9
+ actionProps?: Omit<ComponentProps<'div'>, 'children'>;
10
+ align?: CSSProperties['alignItems'];
14
11
  description?: ReactNode;
15
12
  descriptionProps?: Omit<TextProps, 'children'>;
16
13
  emoji?: string;
17
14
  icon?: IconProps['icon'];
18
15
  iconColor?: IconProps['color'];
19
16
  image?: ReactNode;
20
- imageProps?: Omit<BlockProps, 'children'>;
17
+ imageProps?: Omit<ComponentProps<'div'>, 'children'>;
21
18
  imageSize?: number;
19
+ ref?: Ref<HTMLDivElement>;
22
20
  title?: ReactNode;
23
21
  titleProps?: Omit<TextProps, 'children'>;
24
22
  type?: 'default' | 'page';
23
+ variant?: 'default' | 'dashed';
25
24
  }
26
25
  //#endregion
27
26
  export { EmptyProps };
@@ -2,12 +2,12 @@
2
2
  import FlexBasic_default from "../Flex/FlexBasic.mjs";
3
3
  import { stopPropagation } from "../utils/dom.mjs";
4
4
  import ActionIcon from "../base-ui/ActionIcon/ActionIcon.mjs";
5
+ import Spin from "../base-ui/Spin/Spin.mjs";
5
6
  import SyntaxHighlighter from "../Highlighter/SyntaxHighlighter/index.mjs";
6
7
  import CopyButton from "../CopyButton/CopyButton.mjs";
7
8
  import { downloadBlob } from "../utils/downloadBlob.mjs";
8
9
  import { actionsHoverCls, variants } from "../Highlighter/style.mjs";
9
10
  import { containsScript, isFullHtmlDocument, isHtmlContentClosed } from "./const.mjs";
10
- import NeuralNetworkLoading from "../NeuralNetworkLoading/NeuralNetworkLoading.mjs";
11
11
  import Segmented from "../Segmented/Segmented.mjs";
12
12
  import { HtmlPreviewIframe } from "./Iframe.mjs";
13
13
  import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -285,7 +285,10 @@ const HtmlPreview = memo(({ actionIconSize, actionsRender, animated, bodyRender,
285
285
  /* @__PURE__ */ jsx("div", { className: styles.loadingBackdrop }),
286
286
  /* @__PURE__ */ jsxs("div", {
287
287
  className: styles.loadingBadge,
288
- children: [/* @__PURE__ */ jsx(NeuralNetworkLoading, { size: 16 }), /* @__PURE__ */ jsx("span", { children: "Preparing preview…" })]
288
+ children: [/* @__PURE__ */ jsx(Spin, {
289
+ size: 16,
290
+ variant: "network"
291
+ }), /* @__PURE__ */ jsx("span", { children: "Preparing preview…" })]
289
292
  })
290
293
  ]
291
294
  }), [
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlPreview.mjs","names":["Flexbox"],"sources":["../../src/HtmlPreview/HtmlPreview.tsx"],"sourcesContent":["'use client';\n\nimport { createStaticStyles, cx, keyframes } from 'antd-style';\nimport { Download, Expand } from 'lucide-react';\nimport { memo, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport ActionIcon from '@/base-ui/ActionIcon';\nimport CopyButton from '@/CopyButton';\nimport { Flexbox } from '@/Flex';\nimport { actionsHoverCls, variants } from '@/Highlighter/style';\nimport SyntaxHighlighter from '@/Highlighter/SyntaxHighlighter';\nimport NeuralNetworkLoading from '@/NeuralNetworkLoading';\nimport Segmented from '@/Segmented';\nimport { stopPropagation } from '@/utils/dom';\nimport { downloadBlob } from '@/utils/downloadBlob';\n\nimport { containsScript, DEFAULT_HEIGHT, isFullHtmlDocument, isHtmlContentClosed } from './const';\nimport HtmlPreviewIframe from './Iframe';\nimport type { HtmlPreviewMode, HtmlPreviewProps } from './type';\n\n// Sheen sweep direction: left → right.\n// `background-position` works inversely from \"where the image is drawn\":\n// at `200%` the over-sized gradient starts off to the left of the\n// container, at `-200%` it ends off to the right — so animating\n// 200% → -200% moves the visible bright spot from left to right.\nconst shimmer = keyframes`\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n`;\n\nconst styles = createStaticStyles(({ css, cssVar }) => ({\n loadingBackdrop: css`\n pointer-events: none;\n\n position: absolute;\n z-index: 1;\n inset: 0;\n\n /* Subtle moving sheen so it doesn't look frozen. */\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, ${cssVar.colorText} 4%, transparent) 50%,\n transparent 100%\n );\n background-repeat: no-repeat;\n background-size: 200% 100%;\n\n animation: ${shimmer} 1.6s ${cssVar.motionEaseInOut} infinite;\n `,\n loadingBadge: css`\n position: absolute;\n z-index: 2;\n inset-block-start: 12px;\n inset-inline-start: 12px;\n\n display: inline-flex;\n gap: 8px;\n align-items: center;\n\n padding-block: 4px;\n padding-inline: 6px 10px;\n border-radius: 999px;\n\n font-size: 12px;\n color: ${cssVar.colorTextDescription};\n\n background: ${cssVar.colorBgContainer};\n backdrop-filter: blur(8px);\n box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary};\n `,\n // The streaming source visible during Phase 1 — heavily faded so it\n // reads as \"this is preview-pending content\" rather than the finished\n // article. Auto-follows the tail so the user can see new tokens land\n // even on slow models.\n loadingSource: css`\n pointer-events: none;\n overflow: hidden;\n height: 100%;\n\n /* Faded out so the iframe transition feels like content lighting up,\n not like one document jump-cutting to another. */\n opacity: 0.45;\n\n /* SyntaxHighlighter sets its own background; flatten so the shimmer\n overlay reads cleanly on top. */\n & [data-code-type='highlighter'] {\n background: transparent;\n box-shadow: none;\n }\n\n /* Tail-follow is layout-only — we anchor the scrollable element to\n its scrollHeight via the ref + effect; CSS just keeps the\n overflow hidden. */\n & pre,\n & code {\n background: transparent !important;\n }\n `,\n loadingRoot: css`\n position: relative;\n overflow: hidden;\n background: color-mix(in srgb, ${cssVar.colorText} 3%, ${cssVar.colorBgContainer});\n `,\n // Inline top-right toolbar. Tagged with `actionsHoverCls` so the Highlighter\n // container's `&:hover .${actionsHoverCls} { opacity: 1 }` rule flips it\n // in/out as the user moves over the preview — same UX as the regular code\n // block actions.\n toolbar: cx(\n actionsHoverCls,\n css`\n position: absolute;\n z-index: 2;\n inset-block-start: 8px;\n inset-inline-end: 8px;\n\n padding: 4px;\n border-radius: ${cssVar.borderRadiusLG};\n\n opacity: 0;\n background: ${cssVar.colorBgContainer};\n backdrop-filter: blur(8px);\n box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary};\n\n transition: opacity 0.2s ${cssVar.motionEaseOut};\n\n &:focus-within {\n opacity: 1;\n }\n `,\n ),\n}));\n\nconst themeBackground = (theme?: 'light' | 'dark') => {\n if (theme === 'dark') return '#1f1f1f';\n if (theme === 'light') return '#ffffff';\n return undefined;\n};\n\nconst downloadHtml = async (content: string, fileName: string) => {\n const blob = new Blob([content], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n try {\n await downloadBlob(url, fileName);\n } finally {\n URL.revokeObjectURL(url);\n }\n};\n\nconst HtmlPreview = memo<HtmlPreviewProps>(\n ({\n actionIconSize,\n actionsRender,\n animated,\n bodyRender,\n children,\n className,\n classNames,\n copyable = true,\n defaultHeight,\n defaultMode = 'preview',\n downloadable = true,\n fileName,\n language = 'html',\n onExpand,\n sandbox,\n shadow,\n streamingMode = 'auto',\n style,\n styles: customStyles,\n theme,\n variant = 'filled',\n // `fullFeatured` / `showLanguage` / `defaultExpand` are accepted for API\n // compatibility with the rest of the Pre family but no longer drive a\n // separate header — the inline toolbar is always rendered.\n fullFeatured: _fullFeatured,\n showLanguage: _showLanguage,\n defaultExpand: _defaultExpand,\n ...rest\n }) => {\n const trimmedChildren = useMemo(() => (children || '').trim(), [children]);\n const isFragment = useMemo(() => !isFullHtmlDocument(trimmedChildren), [trimmedChildren]);\n\n // Per-session tracking. Reset on `animated` edge false → true.\n const [scriptLocked, setScriptLocked] = useState(false);\n const [headClosed, setHeadClosed] = useState(false);\n const [liveCommitted, setLiveCommitted] = useState(false);\n const prevAnimatedRef = useRef(animated);\n const lastCommitRef = useRef(0);\n const pendingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const latestContentRef = useRef(trimmedChildren);\n useEffect(() => {\n latestContentRef.current = trimmedChildren;\n }, [trimmedChildren]);\n useEffect(() => {\n if (animated && !prevAnimatedRef.current) {\n setScriptLocked(false);\n setHeadClosed(false);\n setLiveCommitted(false);\n lastCommitRef.current = 0;\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current);\n pendingTimerRef.current = null;\n }\n }\n prevAnimatedRef.current = animated;\n }, [animated]);\n\n // Sticky script detection: once a `<script>` appears in this session,\n // auto mode locks into defer.\n useEffect(() => {\n if (animated && !scriptLocked && containsScript(trimmedChildren)) {\n setScriptLocked(true);\n }\n }, [trimmedChildren, animated, scriptLocked]);\n\n // Track whether the head section has closed. Until it does, the iframe\n // would render either nothing or invalid HTML (style tag mid-stream).\n // After `</head>` (or `</style>` as a fallback for documents that skip\n // an explicit head close) we know the visual baseline is locked in.\n useEffect(() => {\n if (animated && !headClosed) {\n const lowered = trimmedChildren.toLowerCase();\n if (lowered.includes('</head>') || lowered.includes('</style>')) {\n setHeadClosed(true);\n }\n }\n }, [trimmedChildren, animated, headClosed]);\n\n // Two-phase streaming commit:\n // Phase 1 (head still streaming) — don't mount iframe at all. There's\n // nothing meaningful to render and styles aren't applied yet.\n // Phase 2 (head closed, body streaming) — commit at most once every\n // ~250ms. Important: this is a TRUE throttle, not a debounce. The\n // pending timer is held in a ref so it survives effect re-runs;\n // when it fires it commits the latest content (via another ref)\n // and clears itself, allowing a fresh schedule. If chunks come in\n // faster than the throttle window (which they do at ~50/sec) we\n // still get a commit every 250ms instead of waiting for streaming\n // to pause.\n // On streaming end → flush immediately, cancel any pending timer.\n const [throttledContent, setThrottledContent] = useState(trimmedChildren);\n useEffect(() => {\n if (!animated) {\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current);\n pendingTimerRef.current = null;\n }\n lastCommitRef.current = Date.now();\n setThrottledContent(trimmedChildren);\n return;\n }\n if (!headClosed) return;\n\n const throttleMs = 250;\n const now = Date.now();\n const elapsed = now - lastCommitRef.current;\n\n if (elapsed >= throttleMs) {\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current);\n pendingTimerRef.current = null;\n }\n lastCommitRef.current = now;\n setThrottledContent(trimmedChildren);\n return;\n }\n\n // Schedule a future commit, but only if one isn't already pending —\n // every chunk arrival re-runs this effect; we don't want to reset\n // the timer each time (that's debounce, and during continuous\n // streaming it would never fire).\n if (pendingTimerRef.current === null) {\n pendingTimerRef.current = setTimeout(() => {\n lastCommitRef.current = Date.now();\n pendingTimerRef.current = null;\n setThrottledContent(latestContentRef.current);\n }, throttleMs - elapsed);\n }\n }, [trimmedChildren, animated, headClosed]);\n useEffect(\n () => () => {\n if (pendingTimerRef.current) clearTimeout(pendingTimerRef.current);\n },\n [],\n );\n\n // Live-streaming commitment is sticky for the rest of the session. The\n // decision is made the moment the head seals:\n // • `live` → commit unconditionally\n // • `auto` → commit only if no `<script>` has appeared yet (script-\n // bearing docs go down the defer path to avoid running setup() on\n // partial source)\n // • `defer` → never commit; wait for `</html>`\n // Sticky-ness matters for `auto`: if a `<script>` arrives *after* the\n // head has already closed and we've started live-streaming, we keep\n // streaming rather than yanking the rendered content back into a\n // loading state mid-flight. The shell→static swap at end of streaming\n // re-runs the document cleanly anyway.\n useEffect(() => {\n if (!animated || liveCommitted || !headClosed) return;\n if (streamingMode === 'live' || (streamingMode === 'auto' && !scriptLocked)) {\n setLiveCommitted(true);\n }\n }, [animated, headClosed, liveCommitted, scriptLocked, streamingMode]);\n\n // Streaming gate. The iframe can mount in three situations:\n // 1. content is no longer animating\n // 2. `</html>` has arrived\n // 3. live streaming has been committed this session\n const isStable = !animated || isHtmlContentClosed(trimmedChildren) || liveCommitted;\n\n const [mode, setMode] = useState<HtmlPreviewMode>(defaultMode);\n\n // Fragments cannot meaningfully render in preview — force source view.\n // For streaming content that's not yet stable we keep the user's mode\n // choice and substitute a loading placeholder in the body instead, so\n // the toggle UI doesn't flip back and forth as content arrives.\n const effectiveMode: HtmlPreviewMode = isFragment ? 'source' : mode;\n\n const contentRef = useRef(trimmedChildren);\n useEffect(() => {\n contentRef.current = trimmedChildren;\n }, [trimmedChildren]);\n\n // Tail-follow the streaming source visible during Phase 1 — anchor\n // the scroll position to the latest tokens so a slow model's output\n // doesn't sit pinned to the document head while the user waits.\n const loadingSourceRef = useRef<HTMLDivElement | null>(null);\n useEffect(() => {\n if (isStable) return;\n const node = loadingSourceRef.current;\n if (!node) return;\n node.scrollTop = node.scrollHeight;\n }, [trimmedChildren, isStable]);\n\n const getCopyContent = useCallback(() => contentRef.current, []);\n\n const handleDownload = useCallback(() => {\n void downloadHtml(contentRef.current, fileName || 'preview.html');\n }, [fileName]);\n\n const handleExpand = useCallback(() => {\n onExpand?.(contentRef.current);\n }, [onExpand]);\n\n const background = themeBackground(theme);\n\n const sourceBody = useMemo(\n () => (\n <SyntaxHighlighter\n animated={animated}\n className={classNames?.content}\n language={'html'}\n style={{ height: '100%', ...customStyles?.content }}\n variant={variant}\n >\n {trimmedChildren}\n </SyntaxHighlighter>\n ),\n [animated, classNames?.content, customStyles?.content, trimmedChildren, variant],\n );\n\n const iframeBody = useMemo(\n () => (\n <HtmlPreviewIframe\n animated={animated}\n background={background}\n className={classNames?.iframe}\n content={throttledContent}\n defaultHeight={defaultHeight}\n sandbox={sandbox}\n style={customStyles?.iframe}\n />\n ),\n [\n background,\n classNames?.iframe,\n customStyles?.iframe,\n defaultHeight,\n sandbox,\n throttledContent,\n ],\n );\n\n // Shown when the user is on preview mode but the iframe isn't ready\n // yet (Phase 1 of streaming: head still arriving). Holds the eventual\n // iframe height to avoid layout shift on mount.\n //\n // Stream the raw source through `SyntaxHighlighter` at low opacity so\n // the user sees real progress on slow models (a 30-tps DeepSeek\n // pumping a ~5 KB head can otherwise sit on a static spinner for\n // 20+ seconds). A small \"Preparing preview…\" badge keeps the loading\n // state unambiguous. Tail-follow keeps the visible region anchored\n // to the latest tokens — see the `useEffect` below.\n const loadingBody = useMemo(\n () => (\n <div className={styles.loadingRoot} style={{ height: defaultHeight ?? DEFAULT_HEIGHT }}>\n <div className={styles.loadingSource} ref={loadingSourceRef}>\n <SyntaxHighlighter animated={animated} language={'html'} variant={'borderless'}>\n {trimmedChildren}\n </SyntaxHighlighter>\n </div>\n <div className={styles.loadingBackdrop} />\n <div className={styles.loadingBadge}>\n <NeuralNetworkLoading size={16} />\n <span>Preparing preview…</span>\n </div>\n </div>\n ),\n [animated, defaultHeight, trimmedChildren],\n );\n\n const previewBody = isStable ? iframeBody : loadingBody;\n\n const defaultBody = effectiveMode === 'preview' ? previewBody : sourceBody;\n\n const body = useMemo(() => {\n if (!bodyRender) return defaultBody;\n return bodyRender({\n content: trimmedChildren,\n mode: effectiveMode,\n originalNode: defaultBody,\n });\n }, [bodyRender, defaultBody, effectiveMode, trimmedChildren]);\n\n const segmentOptions = useMemo(\n () => [\n { label: 'Preview', value: 'preview' as const },\n { label: 'Source', value: 'source' as const },\n ],\n [],\n );\n\n const iconSize = actionIconSize || 'small';\n\n const originalActions: ReactNode = (\n <>\n {!isFragment && (\n <Segmented\n options={segmentOptions}\n size={'small'}\n value={effectiveMode}\n onChange={(v) => setMode(v as HtmlPreviewMode)}\n />\n )}\n {copyable && <CopyButton content={getCopyContent} size={iconSize} />}\n {downloadable && (\n <ActionIcon\n icon={Download}\n size={iconSize}\n title={'Download HTML'}\n onClick={handleDownload}\n />\n )}\n {onExpand && (\n <ActionIcon\n icon={Expand}\n size={iconSize}\n title={'Open full preview'}\n onClick={handleExpand}\n />\n )}\n </>\n );\n\n const actions = actionsRender\n ? actionsRender({\n actionIconSize: iconSize,\n content: trimmedChildren,\n getContent: getCopyContent,\n mode: effectiveMode,\n originalNode: originalActions,\n setMode,\n })\n : originalActions;\n\n return (\n <div\n className={cx(variants({ shadow, variant }), className)}\n data-code-type=\"html-preview\"\n data-html-preview-language={language}\n style={style}\n {...rest}\n >\n <Flexbox\n horizontal\n align={'center'}\n className={cx(styles.toolbar, classNames?.header)}\n flex={'none'}\n gap={4}\n style={customStyles?.header}\n onClick={stopPropagation}\n >\n {actions}\n </Flexbox>\n {body}\n </div>\n );\n },\n);\n\nHtmlPreview.displayName = 'HtmlPreview';\n\nexport default HtmlPreview;\n"],"mappings":"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"}
1
+ {"version":3,"file":"HtmlPreview.mjs","names":["Flexbox"],"sources":["../../src/HtmlPreview/HtmlPreview.tsx"],"sourcesContent":["'use client';\n\nimport { createStaticStyles, cx, keyframes } from 'antd-style';\nimport { Download, Expand } from 'lucide-react';\nimport { memo, type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport ActionIcon from '@/base-ui/ActionIcon';\nimport Spin from '@/base-ui/Spin';\nimport CopyButton from '@/CopyButton';\nimport { Flexbox } from '@/Flex';\nimport { actionsHoverCls, variants } from '@/Highlighter/style';\nimport SyntaxHighlighter from '@/Highlighter/SyntaxHighlighter';\nimport Segmented from '@/Segmented';\nimport { stopPropagation } from '@/utils/dom';\nimport { downloadBlob } from '@/utils/downloadBlob';\n\nimport { containsScript, DEFAULT_HEIGHT, isFullHtmlDocument, isHtmlContentClosed } from './const';\nimport HtmlPreviewIframe from './Iframe';\nimport type { HtmlPreviewMode, HtmlPreviewProps } from './type';\n\n// Sheen sweep direction: left → right.\n// `background-position` works inversely from \"where the image is drawn\":\n// at `200%` the over-sized gradient starts off to the left of the\n// container, at `-200%` it ends off to the right — so animating\n// 200% → -200% moves the visible bright spot from left to right.\nconst shimmer = keyframes`\n 0% { background-position: 200% 0; }\n 100% { background-position: -200% 0; }\n`;\n\nconst styles = createStaticStyles(({ css, cssVar }) => ({\n loadingBackdrop: css`\n pointer-events: none;\n\n position: absolute;\n z-index: 1;\n inset: 0;\n\n /* Subtle moving sheen so it doesn't look frozen. */\n background: linear-gradient(\n 90deg,\n transparent 0%,\n color-mix(in srgb, ${cssVar.colorText} 4%, transparent) 50%,\n transparent 100%\n );\n background-repeat: no-repeat;\n background-size: 200% 100%;\n\n animation: ${shimmer} 1.6s ${cssVar.motionEaseInOut} infinite;\n `,\n loadingBadge: css`\n position: absolute;\n z-index: 2;\n inset-block-start: 12px;\n inset-inline-start: 12px;\n\n display: inline-flex;\n gap: 8px;\n align-items: center;\n\n padding-block: 4px;\n padding-inline: 6px 10px;\n border-radius: 999px;\n\n font-size: 12px;\n color: ${cssVar.colorTextDescription};\n\n background: ${cssVar.colorBgContainer};\n backdrop-filter: blur(8px);\n box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary};\n `,\n // The streaming source visible during Phase 1 — heavily faded so it\n // reads as \"this is preview-pending content\" rather than the finished\n // article. Auto-follows the tail so the user can see new tokens land\n // even on slow models.\n loadingSource: css`\n pointer-events: none;\n overflow: hidden;\n height: 100%;\n\n /* Faded out so the iframe transition feels like content lighting up,\n not like one document jump-cutting to another. */\n opacity: 0.45;\n\n /* SyntaxHighlighter sets its own background; flatten so the shimmer\n overlay reads cleanly on top. */\n & [data-code-type='highlighter'] {\n background: transparent;\n box-shadow: none;\n }\n\n /* Tail-follow is layout-only — we anchor the scrollable element to\n its scrollHeight via the ref + effect; CSS just keeps the\n overflow hidden. */\n & pre,\n & code {\n background: transparent !important;\n }\n `,\n loadingRoot: css`\n position: relative;\n overflow: hidden;\n background: color-mix(in srgb, ${cssVar.colorText} 3%, ${cssVar.colorBgContainer});\n `,\n // Inline top-right toolbar. Tagged with `actionsHoverCls` so the Highlighter\n // container's `&:hover .${actionsHoverCls} { opacity: 1 }` rule flips it\n // in/out as the user moves over the preview — same UX as the regular code\n // block actions.\n toolbar: cx(\n actionsHoverCls,\n css`\n position: absolute;\n z-index: 2;\n inset-block-start: 8px;\n inset-inline-end: 8px;\n\n padding: 4px;\n border-radius: ${cssVar.borderRadiusLG};\n\n opacity: 0;\n background: ${cssVar.colorBgContainer};\n backdrop-filter: blur(8px);\n box-shadow: 0 0 0 1px ${cssVar.colorBorderSecondary};\n\n transition: opacity 0.2s ${cssVar.motionEaseOut};\n\n &:focus-within {\n opacity: 1;\n }\n `,\n ),\n}));\n\nconst themeBackground = (theme?: 'light' | 'dark') => {\n if (theme === 'dark') return '#1f1f1f';\n if (theme === 'light') return '#ffffff';\n return undefined;\n};\n\nconst downloadHtml = async (content: string, fileName: string) => {\n const blob = new Blob([content], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n try {\n await downloadBlob(url, fileName);\n } finally {\n URL.revokeObjectURL(url);\n }\n};\n\nconst HtmlPreview = memo<HtmlPreviewProps>(\n ({\n actionIconSize,\n actionsRender,\n animated,\n bodyRender,\n children,\n className,\n classNames,\n copyable = true,\n defaultHeight,\n defaultMode = 'preview',\n downloadable = true,\n fileName,\n language = 'html',\n onExpand,\n sandbox,\n shadow,\n streamingMode = 'auto',\n style,\n styles: customStyles,\n theme,\n variant = 'filled',\n // `fullFeatured` / `showLanguage` / `defaultExpand` are accepted for API\n // compatibility with the rest of the Pre family but no longer drive a\n // separate header — the inline toolbar is always rendered.\n fullFeatured: _fullFeatured,\n showLanguage: _showLanguage,\n defaultExpand: _defaultExpand,\n ...rest\n }) => {\n const trimmedChildren = useMemo(() => (children || '').trim(), [children]);\n const isFragment = useMemo(() => !isFullHtmlDocument(trimmedChildren), [trimmedChildren]);\n\n // Per-session tracking. Reset on `animated` edge false → true.\n const [scriptLocked, setScriptLocked] = useState(false);\n const [headClosed, setHeadClosed] = useState(false);\n const [liveCommitted, setLiveCommitted] = useState(false);\n const prevAnimatedRef = useRef(animated);\n const lastCommitRef = useRef(0);\n const pendingTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const latestContentRef = useRef(trimmedChildren);\n useEffect(() => {\n latestContentRef.current = trimmedChildren;\n }, [trimmedChildren]);\n useEffect(() => {\n if (animated && !prevAnimatedRef.current) {\n setScriptLocked(false);\n setHeadClosed(false);\n setLiveCommitted(false);\n lastCommitRef.current = 0;\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current);\n pendingTimerRef.current = null;\n }\n }\n prevAnimatedRef.current = animated;\n }, [animated]);\n\n // Sticky script detection: once a `<script>` appears in this session,\n // auto mode locks into defer.\n useEffect(() => {\n if (animated && !scriptLocked && containsScript(trimmedChildren)) {\n setScriptLocked(true);\n }\n }, [trimmedChildren, animated, scriptLocked]);\n\n // Track whether the head section has closed. Until it does, the iframe\n // would render either nothing or invalid HTML (style tag mid-stream).\n // After `</head>` (or `</style>` as a fallback for documents that skip\n // an explicit head close) we know the visual baseline is locked in.\n useEffect(() => {\n if (animated && !headClosed) {\n const lowered = trimmedChildren.toLowerCase();\n if (lowered.includes('</head>') || lowered.includes('</style>')) {\n setHeadClosed(true);\n }\n }\n }, [trimmedChildren, animated, headClosed]);\n\n // Two-phase streaming commit:\n // Phase 1 (head still streaming) — don't mount iframe at all. There's\n // nothing meaningful to render and styles aren't applied yet.\n // Phase 2 (head closed, body streaming) — commit at most once every\n // ~250ms. Important: this is a TRUE throttle, not a debounce. The\n // pending timer is held in a ref so it survives effect re-runs;\n // when it fires it commits the latest content (via another ref)\n // and clears itself, allowing a fresh schedule. If chunks come in\n // faster than the throttle window (which they do at ~50/sec) we\n // still get a commit every 250ms instead of waiting for streaming\n // to pause.\n // On streaming end → flush immediately, cancel any pending timer.\n const [throttledContent, setThrottledContent] = useState(trimmedChildren);\n useEffect(() => {\n if (!animated) {\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current);\n pendingTimerRef.current = null;\n }\n lastCommitRef.current = Date.now();\n setThrottledContent(trimmedChildren);\n return;\n }\n if (!headClosed) return;\n\n const throttleMs = 250;\n const now = Date.now();\n const elapsed = now - lastCommitRef.current;\n\n if (elapsed >= throttleMs) {\n if (pendingTimerRef.current) {\n clearTimeout(pendingTimerRef.current);\n pendingTimerRef.current = null;\n }\n lastCommitRef.current = now;\n setThrottledContent(trimmedChildren);\n return;\n }\n\n // Schedule a future commit, but only if one isn't already pending —\n // every chunk arrival re-runs this effect; we don't want to reset\n // the timer each time (that's debounce, and during continuous\n // streaming it would never fire).\n if (pendingTimerRef.current === null) {\n pendingTimerRef.current = setTimeout(() => {\n lastCommitRef.current = Date.now();\n pendingTimerRef.current = null;\n setThrottledContent(latestContentRef.current);\n }, throttleMs - elapsed);\n }\n }, [trimmedChildren, animated, headClosed]);\n useEffect(\n () => () => {\n if (pendingTimerRef.current) clearTimeout(pendingTimerRef.current);\n },\n [],\n );\n\n // Live-streaming commitment is sticky for the rest of the session. The\n // decision is made the moment the head seals:\n // • `live` → commit unconditionally\n // • `auto` → commit only if no `<script>` has appeared yet (script-\n // bearing docs go down the defer path to avoid running setup() on\n // partial source)\n // • `defer` → never commit; wait for `</html>`\n // Sticky-ness matters for `auto`: if a `<script>` arrives *after* the\n // head has already closed and we've started live-streaming, we keep\n // streaming rather than yanking the rendered content back into a\n // loading state mid-flight. The shell→static swap at end of streaming\n // re-runs the document cleanly anyway.\n useEffect(() => {\n if (!animated || liveCommitted || !headClosed) return;\n if (streamingMode === 'live' || (streamingMode === 'auto' && !scriptLocked)) {\n setLiveCommitted(true);\n }\n }, [animated, headClosed, liveCommitted, scriptLocked, streamingMode]);\n\n // Streaming gate. The iframe can mount in three situations:\n // 1. content is no longer animating\n // 2. `</html>` has arrived\n // 3. live streaming has been committed this session\n const isStable = !animated || isHtmlContentClosed(trimmedChildren) || liveCommitted;\n\n const [mode, setMode] = useState<HtmlPreviewMode>(defaultMode);\n\n // Fragments cannot meaningfully render in preview — force source view.\n // For streaming content that's not yet stable we keep the user's mode\n // choice and substitute a loading placeholder in the body instead, so\n // the toggle UI doesn't flip back and forth as content arrives.\n const effectiveMode: HtmlPreviewMode = isFragment ? 'source' : mode;\n\n const contentRef = useRef(trimmedChildren);\n useEffect(() => {\n contentRef.current = trimmedChildren;\n }, [trimmedChildren]);\n\n // Tail-follow the streaming source visible during Phase 1 — anchor\n // the scroll position to the latest tokens so a slow model's output\n // doesn't sit pinned to the document head while the user waits.\n const loadingSourceRef = useRef<HTMLDivElement | null>(null);\n useEffect(() => {\n if (isStable) return;\n const node = loadingSourceRef.current;\n if (!node) return;\n node.scrollTop = node.scrollHeight;\n }, [trimmedChildren, isStable]);\n\n const getCopyContent = useCallback(() => contentRef.current, []);\n\n const handleDownload = useCallback(() => {\n void downloadHtml(contentRef.current, fileName || 'preview.html');\n }, [fileName]);\n\n const handleExpand = useCallback(() => {\n onExpand?.(contentRef.current);\n }, [onExpand]);\n\n const background = themeBackground(theme);\n\n const sourceBody = useMemo(\n () => (\n <SyntaxHighlighter\n animated={animated}\n className={classNames?.content}\n language={'html'}\n style={{ height: '100%', ...customStyles?.content }}\n variant={variant}\n >\n {trimmedChildren}\n </SyntaxHighlighter>\n ),\n [animated, classNames?.content, customStyles?.content, trimmedChildren, variant],\n );\n\n const iframeBody = useMemo(\n () => (\n <HtmlPreviewIframe\n animated={animated}\n background={background}\n className={classNames?.iframe}\n content={throttledContent}\n defaultHeight={defaultHeight}\n sandbox={sandbox}\n style={customStyles?.iframe}\n />\n ),\n [\n background,\n classNames?.iframe,\n customStyles?.iframe,\n defaultHeight,\n sandbox,\n throttledContent,\n ],\n );\n\n // Shown when the user is on preview mode but the iframe isn't ready\n // yet (Phase 1 of streaming: head still arriving). Holds the eventual\n // iframe height to avoid layout shift on mount.\n //\n // Stream the raw source through `SyntaxHighlighter` at low opacity so\n // the user sees real progress on slow models (a 30-tps DeepSeek\n // pumping a ~5 KB head can otherwise sit on a static spinner for\n // 20+ seconds). A small \"Preparing preview…\" badge keeps the loading\n // state unambiguous. Tail-follow keeps the visible region anchored\n // to the latest tokens — see the `useEffect` below.\n const loadingBody = useMemo(\n () => (\n <div className={styles.loadingRoot} style={{ height: defaultHeight ?? DEFAULT_HEIGHT }}>\n <div className={styles.loadingSource} ref={loadingSourceRef}>\n <SyntaxHighlighter animated={animated} language={'html'} variant={'borderless'}>\n {trimmedChildren}\n </SyntaxHighlighter>\n </div>\n <div className={styles.loadingBackdrop} />\n <div className={styles.loadingBadge}>\n <Spin size={16} variant=\"network\" />\n <span>Preparing preview…</span>\n </div>\n </div>\n ),\n [animated, defaultHeight, trimmedChildren],\n );\n\n const previewBody = isStable ? iframeBody : loadingBody;\n\n const defaultBody = effectiveMode === 'preview' ? previewBody : sourceBody;\n\n const body = useMemo(() => {\n if (!bodyRender) return defaultBody;\n return bodyRender({\n content: trimmedChildren,\n mode: effectiveMode,\n originalNode: defaultBody,\n });\n }, [bodyRender, defaultBody, effectiveMode, trimmedChildren]);\n\n const segmentOptions = useMemo(\n () => [\n { label: 'Preview', value: 'preview' as const },\n { label: 'Source', value: 'source' as const },\n ],\n [],\n );\n\n const iconSize = actionIconSize || 'small';\n\n const originalActions: ReactNode = (\n <>\n {!isFragment && (\n <Segmented\n options={segmentOptions}\n size={'small'}\n value={effectiveMode}\n onChange={(v) => setMode(v as HtmlPreviewMode)}\n />\n )}\n {copyable && <CopyButton content={getCopyContent} size={iconSize} />}\n {downloadable && (\n <ActionIcon\n icon={Download}\n size={iconSize}\n title={'Download HTML'}\n onClick={handleDownload}\n />\n )}\n {onExpand && (\n <ActionIcon\n icon={Expand}\n size={iconSize}\n title={'Open full preview'}\n onClick={handleExpand}\n />\n )}\n </>\n );\n\n const actions = actionsRender\n ? actionsRender({\n actionIconSize: iconSize,\n content: trimmedChildren,\n getContent: getCopyContent,\n mode: effectiveMode,\n originalNode: originalActions,\n setMode,\n })\n : originalActions;\n\n return (\n <div\n className={cx(variants({ shadow, variant }), className)}\n data-code-type=\"html-preview\"\n data-html-preview-language={language}\n style={style}\n {...rest}\n >\n <Flexbox\n horizontal\n align={'center'}\n className={cx(styles.toolbar, classNames?.header)}\n flex={'none'}\n gap={4}\n style={customStyles?.header}\n onClick={stopPropagation}\n >\n {actions}\n </Flexbox>\n {body}\n </div>\n );\n },\n);\n\nHtmlPreview.displayName = 'HtmlPreview';\n\nexport default HtmlPreview;\n"],"mappings":"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"}
@@ -25,6 +25,7 @@ interface TypographyProps extends DivProps {
25
25
  ref?: Ref<HTMLDivElement>;
26
26
  }
27
27
  interface SyntaxMarkdownProps {
28
+ /** Parse and render sanitized inline HTML in Markdown content. */
28
29
  allowHtml?: boolean;
29
30
  allowHtmlList?: ElementType[];
30
31
  animated?: boolean;
@@ -0,0 +1,6 @@
1
+ import { BadgeProps } from "./type.mjs";
2
+ //#region src/base-ui/Badge/Badge.d.ts
3
+ declare const Badge: import("react").NamedExoticComponent<BadgeProps>;
4
+ //#endregion
5
+ export { Badge as default };
6
+ //# sourceMappingURL=Badge.d.mts.map
@@ -0,0 +1,73 @@
1
+ "use client";
2
+ import { pillSize, statusColor, styles } from "./style.mjs";
3
+ import { memo } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { cx } from "antd-style";
6
+ //#region src/base-ui/Badge/Badge.tsx
7
+ const Badge = memo(({ children, className, color, count, dot = false, offset, overflowCount = 99, ref, showZero = false, size = "default", status, style, text, ...rest }) => {
8
+ if (children == null && (status !== void 0 || text !== void 0)) {
9
+ const dotColor = color ?? statusColor[status ?? "default"];
10
+ return /* @__PURE__ */ jsxs("span", {
11
+ className: cx(styles.statusRoot, className),
12
+ ref,
13
+ style,
14
+ ...rest,
15
+ children: [/* @__PURE__ */ jsx("span", {
16
+ className: cx(styles.statusDot, status === "processing" && styles.statusDotProcessing),
17
+ style: {
18
+ background: dotColor,
19
+ color: dotColor
20
+ }
21
+ }), text && /* @__PURE__ */ jsx("span", {
22
+ className: styles.statusText,
23
+ children: text
24
+ })]
25
+ });
26
+ }
27
+ let content = null;
28
+ let renderPill = dot;
29
+ if (!dot) {
30
+ if (typeof count === "number") {
31
+ if (count !== 0 || showZero) {
32
+ renderPill = true;
33
+ content = count > overflowCount ? `${overflowCount}+` : count;
34
+ }
35
+ } else if (count != null) {
36
+ renderPill = true;
37
+ content = count;
38
+ }
39
+ }
40
+ const pillStyle = {
41
+ background: color,
42
+ transform: offset ? `translate(${offset[0]}px, ${offset[1]}px)` : void 0
43
+ };
44
+ if (children == null) {
45
+ if (!renderPill) return null;
46
+ return /* @__PURE__ */ jsx("span", {
47
+ className: cx(pillSize({ size }), dot && styles.pillDot, className),
48
+ ref,
49
+ style: {
50
+ ...pillStyle,
51
+ ...style
52
+ },
53
+ ...rest,
54
+ children: !dot && content
55
+ });
56
+ }
57
+ return /* @__PURE__ */ jsxs("span", {
58
+ className: cx(styles.wrapper, className),
59
+ ref,
60
+ style,
61
+ ...rest,
62
+ children: [children, renderPill && /* @__PURE__ */ jsx("span", {
63
+ className: cx(pillSize({ size }), styles.pillAbsolute, dot && styles.pillDot),
64
+ style: pillStyle,
65
+ children: !dot && content
66
+ })]
67
+ });
68
+ });
69
+ Badge.displayName = "Badge";
70
+ //#endregion
71
+ export { Badge as default };
72
+
73
+ //# sourceMappingURL=Badge.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.mjs","names":[],"sources":["../../../src/base-ui/Badge/Badge.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { memo, type ReactNode } from 'react';\n\nimport { pillSize, statusColor, styles } from './style';\nimport type { BadgeProps } from './type';\n\nconst Badge = memo<BadgeProps>(\n ({\n children,\n className,\n color,\n count,\n dot = false,\n offset,\n overflowCount = 99,\n ref,\n showZero = false,\n size = 'default',\n status,\n style,\n text,\n ...rest\n }) => {\n const isStatusMode = children == null && (status !== undefined || text !== undefined);\n\n if (isStatusMode) {\n const dotColor = color ?? statusColor[status ?? 'default'];\n\n return (\n <span className={cx(styles.statusRoot, className)} ref={ref} style={style} {...rest}>\n <span\n className={cx(styles.statusDot, status === 'processing' && styles.statusDotProcessing)}\n style={{ background: dotColor, color: dotColor }}\n />\n {text && <span className={styles.statusText}>{text}</span>}\n </span>\n );\n }\n\n let content: ReactNode = null;\n let renderPill = dot;\n\n if (!dot) {\n if (typeof count === 'number') {\n if (count !== 0 || showZero) {\n renderPill = true;\n content = count > overflowCount ? `${overflowCount}+` : count;\n }\n } else if (count != null) {\n renderPill = true;\n content = count;\n }\n }\n\n const pillStyle = {\n background: color,\n transform: offset ? `translate(${offset[0]}px, ${offset[1]}px)` : undefined,\n };\n\n if (children == null) {\n if (!renderPill) return null;\n\n return (\n <span\n className={cx(pillSize({ size }), dot && styles.pillDot, className)}\n ref={ref}\n style={{ ...pillStyle, ...style }}\n {...rest}\n >\n {!dot && content}\n </span>\n );\n }\n\n return (\n <span className={cx(styles.wrapper, className)} ref={ref} style={style} {...rest}>\n {children}\n {renderPill && (\n <span\n className={cx(pillSize({ size }), styles.pillAbsolute, dot && styles.pillDot)}\n style={pillStyle}\n >\n {!dot && content}\n </span>\n )}\n </span>\n );\n },\n);\n\nBadge.displayName = 'Badge';\n\nexport default Badge;\n"],"mappings":";;;;;;AAQA,MAAM,QAAQ,MACX,EACC,UACA,WACA,OACA,OACA,MAAM,OACN,QACA,gBAAgB,IAChB,KACA,WAAW,OACX,OAAO,WACP,QACA,OACA,MACA,GAAG,WACC;CAGJ,IAFqB,YAAY,SAAS,WAAW,KAAA,KAAa,SAAS,KAAA,IAEzD;EAChB,MAAM,WAAW,SAAS,YAAY,UAAU;EAEhD,OACE,qBAAC,QAAD;GAAM,WAAW,GAAG,OAAO,YAAY,SAAS;GAAQ;GAAY;GAAO,GAAI;GAA/E,UAAA,CACE,oBAAC,QAAD;IACE,WAAW,GAAG,OAAO,WAAW,WAAW,gBAAgB,OAAO,mBAAmB;IACrF,OAAO;KAAE,YAAY;KAAU,OAAO;IAAS;GAChD,CAAA,GACA,QAAQ,oBAAC,QAAD;IAAM,WAAW,OAAO;IAAa,UAAA;GAAW,CAAA,CACrD;;CAEV;CAEA,IAAI,UAAqB;CACzB,IAAI,aAAa;CAEjB,IAAI,CAAC,KAAK;EACR,IAAI,OAAO,UAAU,UACf;OAAA,UAAU,KAAK,UAAU;IAC3B,aAAa;IACb,UAAU,QAAQ,gBAAgB,GAAG,cAAc,KAAK;GAC1D;SACK,IAAI,SAAS,MAAM;GACxB,aAAa;GACb,UAAU;EACZ;CACF;CAEA,MAAM,YAAY;EAChB,YAAY;EACZ,WAAW,SAAS,aAAa,OAAO,GAAG,MAAM,OAAO,GAAG,OAAO,KAAA;CACpE;CAEA,IAAI,YAAY,MAAM;EACpB,IAAI,CAAC,YAAY,OAAO;EAExB,OACE,oBAAC,QAAD;GACE,WAAW,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,OAAO,OAAO,SAAS,SAAS;GAC7D;GACL,OAAO;IAAE,GAAG;IAAW,GAAG;GAAM;GAChC,GAAI;GAEH,UAAA,CAAC,OAAO;EACL,CAAA;CAEV;CAEA,OACE,qBAAC,QAAD;EAAM,WAAW,GAAG,OAAO,SAAS,SAAS;EAAQ;EAAY;EAAO,GAAI;EAA5E,UAAA,CACG,UACA,cACC,oBAAC,QAAD;GACE,WAAW,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,OAAO,cAAc,OAAO,OAAO,OAAO;GAC5E,OAAO;GAEN,UAAA,CAAC,OAAO;EACL,CAAA,CAEJ;;AAEV,CACF;AAEA,MAAM,cAAc"}
@@ -0,0 +1,3 @@
1
+ import { BadgeProps, BadgeSize, BadgeStatus } from "./type.mjs";
2
+ import Badge from "./Badge.mjs";
3
+ export { type BadgeProps, type BadgeSize, type BadgeStatus, Badge as default };