From f65ad86f0663b22585def7502e71a6c10ad852be Mon Sep 17 00:00:00 2001 From: catouse Date: Mon, 20 Nov 2023 06:41:02 +0000 Subject: [PATCH] deploy: 3bcd1a22cfc0e230f4b47bc6239a1a5388b80273 --- 3/404.html | 6 +++--- 3/frames/zui.html | 6 +++--- 3/guide/config/base/color.html | 6 +++--- 3/guide/config/base/font.html | 6 +++--- 3/guide/config/base/rounded.html | 6 +++--- 3/guide/config/base/screens.html | 6 +++--- 3/guide/config/base/shadow.html | 6 +++--- 3/guide/config/base/spacing.html | 6 +++--- 3/guide/customize/build.html | 6 +++--- 3/guide/customize/dev.html | 6 +++--- 3/guide/customize/exts-lib.html | 6 +++--- 3/guide/index.html | 6 +++--- 3/guide/start/index.html | 6 +++--- 3/hashmap.json | 2 +- 3/index.html | 6 +++--- 3/lib/components/alert/index.html | 6 +++--- 3/lib/components/avatar-group/index.html | 6 +++--- 3/lib/components/avatar/index.html | 6 +++--- 3/lib/components/avatar/js.html | 6 +++--- 3/lib/components/breadcrumb/index.html | 6 +++--- 3/lib/components/btn-group/index.html | 6 +++--- 3/lib/components/btn-group/js.html | 6 +++--- 3/lib/components/button/index.html | 6 +++--- 3/lib/components/button/js.html | 6 +++--- 3/lib/components/color-picker/index.html | 6 +++--- 3/lib/components/contextmenu/index.html | 6 +++--- 3/lib/components/dashboard/index.html | 6 +++--- 3/lib/components/datetime-picker/date.html | 6 +++--- 3/lib/components/datetime-picker/datetime.html | 6 +++--- 3/lib/components/datetime-picker/time.html | 6 +++--- 3/lib/components/dropdown/index.html | 6 +++--- 3/lib/components/kanban/index.html | 6 +++--- 3/lib/components/label/index.html | 6 +++--- 3/lib/components/menu/index.html | 6 +++--- 3/lib/components/menu/js.html | 6 +++--- 3/lib/components/messager/index.html | 6 +++--- 3/lib/components/modal/index.html | 6 +++--- 3/lib/components/modal/js.html | 6 +++--- 3/lib/components/nav/index.html | 6 +++--- 3/lib/components/nav/js.html | 6 +++--- 3/lib/components/pager/index.html | 6 +++--- 3/lib/components/pager/js.html | 6 +++--- 3/lib/components/panel/index.html | 6 +++--- 3/lib/components/picker/index.html | 6 +++--- 3/lib/components/progress-circle/index.html | 6 +++--- 3/lib/components/progress/index.html | 6 +++--- 3/lib/components/scrollbar/index.html | 6 +++--- 3/lib/components/search-box/index.html | 6 +++--- 3/lib/components/table/index.html | 6 +++--- 3/lib/components/tabs/index.html | 6 +++--- 3/lib/components/toolbar/index.html | 6 +++--- 3/lib/components/toolbar/js.html | 6 +++--- 3/lib/components/tooltip/index.html | 6 +++--- 3/lib/components/tree/index.html | 6 +++--- 3/lib/components/upload-imgs/index.html | 6 +++--- 3/lib/components/upload/index.html | 6 +++--- 3/lib/dtable/dtable/index.html | 6 +++--- 3/lib/dtable/dtable/plugins.html | 6 +++--- 3/lib/forms/checkbox/index.html | 6 +++--- 3/lib/forms/form/index.html | 6 +++--- 3/lib/forms/input-control/index.html | 6 +++--- 3/lib/forms/input-group/index.html | 6 +++--- 3/lib/helpers/core/cash.html | 6 +++--- 3/lib/helpers/core/component.html | 6 +++--- 3/lib/helpers/helpers/index.html | 6 +++--- 3/lib/helpers/store/index.html | 6 +++--- 3/lib/icons/icons/index.html | 6 +++--- 3/lib/index.html | 6 +++--- 3/public/icons/fontawesome-license.html | 6 +++--- 3/themes/index.html | 6 +++--- 3/utilities/backgrounds/utilities/index.html | 6 +++--- 3/utilities/borders/utilities/border-color.html | 6 +++--- 3/utilities/borders/utilities/border-radius.html | 6 +++--- 3/utilities/borders/utilities/border-width.html | 6 +++--- 3/utilities/effects/utilities/animation.html | 6 +++--- 3/utilities/effects/utilities/filter.html | 6 +++--- 3/utilities/effects/utilities/flip.html | 6 +++--- 3/utilities/effects/utilities/opacity.html | 6 +++--- 3/utilities/effects/utilities/rotate.html | 6 +++--- 3/utilities/effects/utilities/scale.html | 6 +++--- 3/utilities/effects/utilities/shadow.html | 6 +++--- 3/utilities/flex/utilities/align-content.html | 6 +++--- 3/utilities/flex/utilities/align-items.html | 6 +++--- 3/utilities/flex/utilities/align-self.html | 6 +++--- 3/utilities/flex/utilities/basis.html | 6 +++--- 3/utilities/flex/utilities/direction.html | 6 +++--- 3/utilities/flex/utilities/flex.html | 6 +++--- 3/utilities/flex/utilities/gap.html | 6 +++--- 3/utilities/flex/utilities/grow.html | 6 +++--- 3/utilities/flex/utilities/justify-content.html | 6 +++--- 3/utilities/flex/utilities/order.html | 6 +++--- 3/utilities/flex/utilities/shrink.html | 6 +++--- 3/utilities/flex/utilities/wrap.html | 6 +++--- 3/utilities/index.html | 6 +++--- 3/utilities/interactivity/utilities/disabled.html | 6 +++--- 3/utilities/interactivity/utilities/pointer-events.html | 6 +++--- 3/utilities/interactivity/utilities/scroll.html | 6 +++--- 3/utilities/interactivity/utilities/state.html | 6 +++--- 3/utilities/interactivity/utilities/user-select.html | 6 +++--- 3/utilities/layout/utilities/aspect-ratio.html | 6 +++--- 3/utilities/layout/utilities/container.html | 6 +++--- 3/utilities/layout/utilities/display.html | 6 +++--- 3/utilities/layout/utilities/floats.html | 6 +++--- 3/utilities/layout/utilities/object-fit.html | 6 +++--- 3/utilities/layout/utilities/overflow.html | 6 +++--- 3/utilities/layout/utilities/position.html | 6 +++--- 3/utilities/layout/utilities/top-right-bottom-left.html | 6 +++--- 3/utilities/layout/utilities/visibility.html | 6 +++--- 3/utilities/layout/utilities/z-index.html | 6 +++--- 3/utilities/sizing/utilities/height.html | 6 +++--- 3/utilities/sizing/utilities/width.html | 6 +++--- 3/utilities/spacing/utilities/margin.html | 6 +++--- 3/utilities/spacing/utilities/padding.html | 6 +++--- 3/utilities/spacing/utilities/space.html | 6 +++--- 3/utilities/style/utilities/outline.html | 6 +++--- 3/utilities/style/utilities/pale.html | 6 +++--- 3/utilities/style/utilities/solid.html | 6 +++--- 3/utilities/typography/utilities/font-family.html | 6 +++--- 3/utilities/typography/utilities/font-size.html | 6 +++--- 3/utilities/typography/utilities/font-weight.html | 6 +++--- 3/utilities/typography/utilities/leading.html | 6 +++--- 3/utilities/typography/utilities/line-clamp.html | 6 +++--- 3/utilities/typography/utilities/text-align.html | 6 +++--- 3/utilities/typography/utilities/text-color.html | 6 +++--- 3/utilities/typography/utilities/text-overflow.html | 6 +++--- 3/utilities/typography/utilities/vertical-align.html | 6 +++--- 3/utilities/typography/utilities/whitespace.html | 6 +++--- 3/utilities/typography/utilities/word-break.html | 6 +++--- 3/zui.js | 1 + 3/zui.js.map | 2 +- 3/zui.umd.cjs | 2 +- 3/zui.umd.cjs.map | 2 +- 132 files changed, 386 insertions(+), 385 deletions(-) diff --git a/3/404.html b/3/404.html index 06c5552ebd..1deb177e9d 100644 --- a/3/404.html +++ b/3/404.html @@ -10,12 +10,12 @@ - - + +
Skip to content

404

PAGE NOT FOUND

But if you don't change your direction, and if you keep looking, you may end up where you are heading.

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/frames/zui.html b/3/frames/zui.html index a6f8f4efe6..5ca6097059 100644 --- a/3/frames/zui.html +++ b/3/frames/zui.html @@ -13,14 +13,14 @@ - - + +
- + \ No newline at end of file diff --git a/3/guide/config/base/color.html b/3/guide/config/base/color.html index 083d89c4b6..d33103b160 100644 --- a/3/guide/config/base/color.html +++ b/3/guide/config/base/color.html @@ -13,8 +13,8 @@ - - + +
Skip to content

颜色

ZUI 的颜色体系基于 TailwindCSS 调色板 实现,主要包含语义化调色板、界面公共颜色和特殊颜色。下面分别进行介绍。

语义化调色板

ZUI 内置了 8 种语义化调色板,每种类型都来自 TailwindCSS 内置的调色板,你可以根据产品中的需要来更换现有调色板。

PRIMARY 主要
品牌、主题、可交互、正常
--color-primary-50
50
--color-primary-100
100
--color-primary-200
200
--color-primary-300
300
--color-primary-400
400
--color-primary-500
500
--color-primary-600
600
--color-primary-700
700
--color-primary-800
800
--color-primary-900
900
--color-primary-950
950
SECONDARY 次要
品牌、主题、次级、常态的
--color-secondary-50
50
--color-secondary-100
100
--color-secondary-200
200
--color-secondary-300
300
--color-secondary-400
400
--color-secondary-500
500
--color-secondary-600
600
--color-secondary-700
700
--color-secondary-800
800
--color-secondary-900
900
--color-secondary-950
950
SUCCESS 成功
完成、积极
--color-success-50
50
--color-success-100
100
--color-success-200
200
--color-success-300
300
--color-success-400
400
--color-success-500
500
--color-success-600
600
--color-success-700
700
--color-success-800
800
--color-success-900
900
--color-success-950
950
WARNING 关注
提示、重点
--color-warning-50
50
--color-warning-100
100
--color-warning-200
200
--color-warning-300
300
--color-warning-400
400
--color-warning-500
500
--color-warning-600
600
--color-warning-700
700
--color-warning-800
800
--color-warning-900
900
--color-warning-950
950
DANGER 警告
提示、异常、警醒
--color-danger-50
50
--color-danger-100
100
--color-danger-200
200
--color-danger-300
300
--color-danger-400
400
--color-danger-500
500
--color-danger-600
600
--color-danger-700
700
--color-danger-800
800
--color-danger-900
900
--color-danger-950
950
IMPORTANT 重要
优先
--color-important-50
50
--color-important-100
100
--color-important-200
200
--color-important-300
300
--color-important-400
400
--color-important-500
500
--color-important-600
600
--color-important-700
700
--color-important-800
800
--color-important-900
900
--color-important-950
950
SPECIAL 特殊
触动、激情
--color-special-50
50
--color-special-100
100
--color-special-200
200
--color-special-300
300
--color-special-400
400
--color-special-500
500
--color-special-600
600
--color-special-700
700
--color-special-800
800
--color-special-900
900
--color-special-950
950
GRAY 灰色
中立、背景、边界
--color-gray-50
50
--color-gray-100
100
--color-gray-200
200
--color-gray-300
300
--color-gray-400
400
--color-gray-500
500
--color-gray-600
600
--color-gray-700
700
--color-gray-800
800
--color-gray-900
900
--color-gray-950
950

提示

点击调色板中的颜色,可以复制颜色变量名称方便在代码中使用。

界面公共颜色

在 ZUI 中,界面上公共的颜色已被精心梳理和定义,尽可能使用更少的颜色来定义大部分界面元素上可能用到的颜色。界面公共颜色都应该来自语义化调色板,你可以根据产品中的需要来更换其他调色板。下面是这些颜色的定义:

--color-canvas
CANVAS 画布颜色
通常用于页面背景、组件背景等,在浅色主题中为白色,在深色主题中为深黑色。
--color-inverse
INVERSE 画布反色
通常用于界面突出部分的背景或文字颜色,例如工具提示背景等,在浅色主题中为黑色,在深色主题中为白色。
--color-surface
SURFACE 控件背景
用于控件的背景颜色,例如按钮背景、可交互面板背景等,在浅色主题中为浅灰色,在深色主题中为深黑色。
--color-fore
FORE 文本颜色
默认的文本颜色,在浅色主题中为深黑色,在深色主题中为浅灰色。
--color-focus
FOCUS 焦点颜色
可聚焦控件的焦点状态指示颜色,例如按钮获得焦点的轮廓颜色。
--color-link
LINK 链接颜色
链接的颜色,例如超链接、按钮链接等,通常与主题色保持一致。
--color-link-hover
LINK-HOVER 链接悬停颜色
链接的在鼠标悬停状态时的颜色
--color-link-visited
LINK-VISITED 链接访问后的颜色
链接的在点击访问后的颜色
--color-placeholder
PLACEHOLDER 占位文本颜色
通常用于输入框的占位文本颜色
--color-border
BORDER 边框颜色
控件的边框颜色
--color-border-strong
BORDER-STRONG 加重的边框颜色
加重的控件的边框颜色
--color-border-light
BORDER-LIGHT 轻量的边框颜色
轻量的控件的边框颜色

特殊颜色

在 ZUI 中会用到一些特殊颜色,这些颜色的定义是固定的,不会因为更换主题或调色板而改变。下面是这些颜色的定义:

--color-white
WHITE 白色
永远为纯白色 #FFFFFF,不会受主题影响
--color-black
BLACK 黑色
永远为纯黑色 #000000,不会受主题影响
--color-transparent
TRANSPARENT 透明色
Alpha 通道永远为 0,不会受主题影响
--color-inherit
INHERIT 继承色
继承父元素同属性的颜色值,由 CSS color 属性值 inherit 提供。
--color-current
CURRENT 当前色
继承父元素文本颜色属性的值,由 CSS color 属性值 currentColor 提供。

使用颜色

你拥有多种方式来使用颜色,下面分别进行介绍。

通过 CSS 变量

每种语义化颜色都被定义为 CSS 变量,变量名称拥有相同的格式,都以 --color- 开头,然后通过 - 连接颜色名称得到。例如 CSS 变量 --color-primary-500 可以引用 Primary 调色板上的第 500 号颜色。下面为一个在 HTML 代码中使用的例子:

这是一段使用 Primary 调色板上的第 500 号颜色的文本

html
<h4 style="color: var(--color-primary-500)">
@@ -46,7 +46,7 @@
   --color-primary-900-rgb: 88, 34, 133;
   --color-primary-950-rgb: 59, 14, 99;
 }

提示

在定义 CSS 变量覆盖调色板时,除了定义 50~950 的十六进制颜色外,还需要定义对应的 RGB 颜色,这是为了在一些特殊场景下通过改变透明度来实现颜色的变化。

注意

如果你需要自定义配色,建议只通过修改调色板来实现,不建议修改界面公共颜色,除非主题需要实现对比度更明显的风格,任何时候都不应该修改特殊颜色的定义。

更多关于主题的内容参考 主题 文档。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/config/base/font.html b/3/guide/config/base/font.html index 3eabaf2636..19bcfb1fd6 100644 --- a/3/guide/config/base/font.html +++ b/3/guide/config/base/font.html @@ -13,8 +13,8 @@ - - + +
Skip to content

字体

字体配置包含字体、字号、字重和行高多个部分,下面分别进行介绍。

字体风格

字体用于设置文本呈现的风格,在 ZUI 中预设了三种字体风格,包括无衬线字体、衬线字体和等宽字体。下面为三种字体的直观展示:

font-sans
.font-sans
无衬线字体 默认字体,易于阅读,通常用于正文
The quick brown fox jumps over the lazy dog.
@@ -41,7 +41,7 @@
 月光如流水一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦。
leading-relaxed
.leading-relaxed
宽松
line-height: line-height
So I started to walk into the water. I won't lie to you boys, I was terrified. But I pressed on, and as I made my way past the breakers a strange calm came over me. I don't know if it was divine intervention or the kinship of all living things but I tell you Jerry at that moment, I was a marine biologist.
 月光如流水一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦。
leading-loose
.leading-loose
松散
line-height: line-height
So I started to walk into the water. I won't lie to you boys, I was terrified. But I pressed on, and as I made my way past the breakers a strange calm came over me. I don't know if it was divine intervention or the kinship of all living things but I tell you Jerry at that moment, I was a marine biologist.
 月光如流水一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦。

在 ZUI 中可以通过 CSS 工具类来设置行高,详细用法参加 CSS 工具类 / 排版 / 行高 文档。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/config/base/rounded.html b/3/guide/config/base/rounded.html index 9fcf8688ba..c83278c7e0 100644 --- a/3/guide/config/base/rounded.html +++ b/3/guide/config/base/rounded.html @@ -13,8 +13,8 @@ - - + +
Skip to content

圆角

圆角配置

圆角能让界面元素更加具有亲和力,在 ZUI 中预设了一系列的圆角,具体如下:

.rounded-none
无圆角
--radius-none
--radius-none
border-radius
.rounded-sm
小圆角
--radius-sm
--radius-sm
border-radius
.rounded
默认圆角
--radius
--radius
border-radius
.rounded-md
中等圆角
--radius-md
--radius-md
border-radius
.rounded-lg
大圆角
--radius-lg
--radius-lg
border-radius
.rounded-xl
超大圆角
--radius-xl
--radius-xl
border-radius
.rounded-2xl
2x 超大圆角
--radius-2xl
--radius-2xl
border-radius
.rounded-3xl
3x 超大圆角
--radius-3xl
--radius-3xl
border-radius
.rounded-full
完整圆角
--radius-full
--radius-full
border-radius

使用圆角

通过 CSS 工具类

在 ZUI 中可以通过 CSS 工具类来设置圆角,详细用法参加 CSS 工具类 / 边框 / 边框圆角 文档。下面为一个简单的例子:

小圆角
大圆角
html
<div class="p-4 rounded-sm secondary">小圆角</div>
@@ -30,7 +30,7 @@
   --radius-3xl:     1.5rem;
   --radius-full:    9999px;
 }

自定义主题

可以通过定制主题来修改圆角设置,具体参见 主题 文档。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/config/base/screens.html b/3/guide/config/base/screens.html index ea04aa80f8..25987f5e49 100644 --- a/3/guide/config/base/screens.html +++ b/3/guide/config/base/screens.html @@ -13,8 +13,8 @@ - - + +
Skip to content

屏幕

屏幕断点

在 ZUI 中定义了一系列屏幕断点,你可以通过这些断点来实现响应式布局。下面为断点配置信息:

屏幕断点内部名称CSS 变量尺寸范围
超小尺寸xs< --screen-sm
小尺寸sm--screen-sm--screen-sm
中等尺寸md--screen-md--screen-md
大尺寸lg--screen-lg--screen-lg
超大尺寸xl--screen-xl--screen-xl
2x 超大尺寸2xl--screen-2xl--screen-2xl

使用断点

通过 .container 工具类

使用屏幕断点最简单的方式为使用 CSS 工具类 .container,此工具类会让所属元素成为一个随屏幕宽度自动响应的容器。下面为一个示例:

自适应容器
html
<div class="container">自适应容器</div>

了解 .container 工具类的更多用法可以参考 CSS 工具类 / 布局 / 容器 文档。

通过 CSS 变量

你可以通过 CSS 变量来获取屏幕断点的值,下面为通过 CSS 变量实现 .container 工具类的示例:

css
.-container {
@@ -51,7 +51,7 @@
   --screen-xl:  1280px;
   --screen-2xl: 1536px;
 }

自定义主题

可以通过定制主题来修改屏幕断点设置,具体参见 主题 文档。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/config/base/shadow.html b/3/guide/config/base/shadow.html index a9edbb18de..a3fe2f6e66 100644 --- a/3/guide/config/base/shadow.html +++ b/3/guide/config/base/shadow.html @@ -13,8 +13,8 @@ - - + +
Skip to content

阴影

阴影配置

阴影能让界面元素更加具有层次感,在 ZUI 中预设了一系列的阴影,具体如下:

预览
阴影名称
CSS 变量名
box-shadow 实际值
.shadow-inner
内部阴影
--shadow-inner
--shadow-inner
box-shadow
.shadow-none
无阴影
--shadow-none
--shadow-none
box-shadow
.shadow-sm
小阴影
--shadow-sm
--shadow-sm
box-shadow
.shadow
默认阴影
--shadow
--shadow
box-shadow
.shadow-md
中等阴影
--shadow-md
--shadow-md
box-shadow
.shadow-lg
大阴影
--shadow-lg
--shadow-lg
box-shadow
.shadow-xl
超大阴影
--shadow-xl
--shadow-xl
box-shadow
.shadow-2xl
2x 超大阴影
--shadow-2xl
--shadow-2xl
box-shadow

使用阴影

通过 CSS 工具类

在 ZUI 中可以通过 CSS 工具类来设置阴影,详细用法参加 CSS 工具类 / 效果 / 盒阴影 文档。下面为一个简单的例子:

小阴影
大阴影
html
<div class="p-4 shadow-sm canvas">小阴影</div>
@@ -29,7 +29,7 @@
   --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
   --shadow-none:  none;
 }

自定义主题

可以通过定制主题来修改阴影设置,具体参见 主题 文档。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/config/base/spacing.html b/3/guide/config/base/spacing.html index 79aaded71d..c9b75eafd1 100644 --- a/3/guide/config/base/spacing.html +++ b/3/guide/config/base/spacing.html @@ -13,12 +13,12 @@ - - + +
Skip to content

间距

间距配置

为了方便实现风格一致的交互界面,ZUI 预置了间距设置。下面为默认的间距配置:

名称
实际值
预览
0
width
px
width
0.5
width
1
width
1.5
width
2
width
2.5
width
3
width
3.5
width
4
width
5
width
6
width
7
width
8
width
9
width
10
width
11
width
12
width
14
width
16
width
20
width
24
width
28
width
32
width
36
width
40
width
44
width
48
width
52
width
56
width
60
width
64
width
72
width
80
width
96
width

4px 约定

通过上表可以看到,除了 0px 比较特殊的设置,其他间距实际值都是 4px 的倍数,这是有意设计,无论是设计还是开发都应该将间距为 4px 的倍数作为约定,这样更有利于实现风格一致的交互界面。

当以上间距无法满足要求时,如果需要引入新的间距值也应当遵从 4px 约定。

间距会影响所有相关 CSS 属性配置,包括 paddingmarginwidthheightmaxHeightgapinset 等。

使用间距

在 ZUI 中提供了大量 CSS 工具类,可以非常方便的来应用间距配置,包括:

如需了解,请参考对应的文档。

自定义间距

可以通过定制主题来修改间距设置,具体参见 主题 文档。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/customize/build.html b/3/guide/customize/build.html index 66ac4116a8..9de939872c 100644 --- a/3/guide/customize/build.html +++ b/3/guide/customize/build.html @@ -13,12 +13,12 @@ - - + +
Skip to content

打包

执行如下命令进行打包操作:

sh
pnpm build

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/customize/dev.html b/3/guide/customize/dev.html index 759c216d19..c63a6dd3f5 100644 --- a/3/guide/customize/dev.html +++ b/3/guide/customize/dev.html @@ -13,12 +13,12 @@ - - + +
Skip to content

开发

开发服务

执行如下命令启动开发服务:

shell
$ pnpm dev

开发服务器启动后,默认情况下可以通过网址:http://localhost:5173/ 来访问开发服务页面。通过页面上的组件导航,可以访问对应的组件开发页面。也可以将组件名附加到网址后面,直接访问对应的组件页面,例如 http://localhost:5173/button/

在开发服务页面上支持热更新,当开发文件变更后会自动反馈到开发服务页面上。

对组件进行开发调试

组件开发目录

ZUI3 每个组件在一个独立的目录内,拥有自己的 package.json 文件,使得组件可以独立作为 npm 包来使用,也可以单独作为子项目进行开发维护。

提示

通常组件通过在 package.json 文件中设置属性 private: true 来让包仅在 zui3 工作空间内可用,但组件仍然拥有作为公开的包发布到 npm 上进行独立使用。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/customize/exts-lib.html b/3/guide/customize/exts-lib.html index 2f5a0ab89d..0dc500c19d 100644 --- a/3/guide/customize/exts-lib.html +++ b/3/guide/customize/exts-lib.html @@ -13,14 +13,14 @@ - - + +
Skip to content

组件库扩展

ZUI3 组件库内置了大量组件,并支持集中开发、调试和打包,其中打包还支持只选择指定的组件进行个性化定制,同步输出组件库文档。但当需求扩展到组件库之外时,就需要用到扩展组件库了。ZUI3 支持扩展组件库模式,可以从其他位置引入一个或多个组件库目录,享受集中开发、调试和打包。下面介绍扩展组件库的使用方法。

定义扩展库

扩展组件库可以来自本地系统的任意位置,只需要提供一个路径,例如:

txt
/Users/TaiJi/Projects/zui3_exts/lib/

扩展组件库的目录结构与 ZUI3 /lib/ 下的目录结构一致,下面的每个子目录为一个独立的组件,详细定义参考 开发文档

添加扩展库

zui3 项目根目录执行:

shell
$ pnpm extend-lib -- <ext_lib_path> <lib_name>

其中参数 ext_lib_path 为扩展组件库路径,<lib_name> 为扩展组件库名称。例如:

shell
$ pnpm extend-lib -- /Users/TaiJi/Projects/zui3_exts/lib/ zentao

执行上述命令之后,会将组件库目录文件拷贝到 zui3/lib_name 目录下,同时会在 zui3/exts/libs.json 文件中记录此扩展库的名称和路径。

json
{
     "zentao": "/Users/TaiJi/Projects/zui3_exts/lib/*"
 }

实际上,你也可以通过自己编辑这个文件来添加扩展库。

启动开发服务

要在开发模式中包含对扩展组件库的开发调试,只需要执行如下命令代替 pnpm dev 命令即可:

shell
$ pnpm dev:exts

当添加了多个扩展库时,上述命令会包含所有扩展库,有时只需要包含特定的扩展库,只需要自定义 --lib 参数即可:

shell
$ pnpm dev:exts --lib=zui,zentao

启动文档服务器

要在文档网站服务模式中包含对扩展组件库的文档支持,只需要如下命令代替 pnpm docs:dev 命令即可:

shell
$ pnpm docs:dev:exts

打包

打包时如果需要将扩展库中的组件也进行打包,则需要添加 --exts 参数,然后就可以在需要打包的组件清单中指定扩展库中的组件名称:

shell
$ pnpm build -- label @zentao/status-label --exts

如果不指定名称,则默认打包仍然只打包内置组件库的组件,例如下面的命令仍然相当于 pnpm build

shell
$ pnpm build -- --exts

如果需要将所有内置组件库和扩展库中的所有组件一并打包,可以使用如下命令:

shell
$ pnpm build -- zui+exts --exts --name=zentao

当添加了多个扩展库时,上述命令会包含所有扩展库,有时只需要包含特定的扩展库,只需要自定义 --exts 参数即可:

shell
$ pnpm build -- zui+exts --exts=zui,zentao

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/index.html b/3/guide/index.html index 11e3bce9f5..fe8808c8f8 100644 --- a/3/guide/index.html +++ b/3/guide/index.html @@ -13,12 +13,12 @@ - - + +
Skip to content

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/guide/start/index.html b/3/guide/start/index.html index a58f0a8478..d8e43b1ad9 100644 --- a/3/guide/start/index.html +++ b/3/guide/start/index.html @@ -13,12 +13,12 @@ - - + +
Skip to content

快速开始

兼容性

支持的浏览器

  • Chrome:49+
  • Firefox:45+
  • Safari:10+
  • Edge:13+
  • Chrome for Android:112+
  • iOS Safari:10+

关键特性

JS

  • letconst
  • ✅ 箭头函数
  • ✅ 模版字符串
  • class
  • symbol
  • SetMap
  • Promise
  • ✅ 扩展运算符 ...
  • Object.assignObject.keys
  • 🚫 Object.entriesObject.values
  • 🚫 asyncawait
  • 🚫 解构赋值

CSS

  • var()
  • calc()
  • 🚫 vwvh

第三方依赖

如果把握不准对照支持的浏览器参考 https://caniuse.com/

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/hashmap.json b/3/hashmap.json index 4c036db310..57e6943180 100644 --- a/3/hashmap.json +++ b/3/hashmap.json @@ -1 +1 @@ -{"frames_zui.md":"4be9ad3d","guide_config_base_font.md":"753af1aa","guide_config_base_rounded.md":"497eea65","guide_config_base_color.md":"b6804a31","guide_config_base_screens.md":"926a9a4b","guide_config_base_shadow.md":"4d29d2d1","guide_customize_build.md":"1d34ab5f","guide_customize_dev.md":"2553e635","guide_index.md":"de433d51","guide_customize_exts-lib.md":"2efbea3a","index.md":"1a1fd727","lib_components_alert_index.md":"42e0e4d9","lib_components_avatar_js.md":"f77ad499","lib_components_breadcrumb_index.md":"08e2da11","lib_components_avatar-group_index.md":"cd61e60a","lib_components_avatar_index.md":"ab8fe9b0","guide_start_index.md":"9fbc81bf","lib_components_btn-group_index.md":"a1a6f70b","guide_config_base_spacing.md":"20eca320","lib_components_progress-circle_index.md":"de2e126b","lib_components_tree_index.md":"c191866d","lib_components_picker_index.md":"56bec2ee","lib_components_button_index.md":"e99c9e3f","lib_components_datetime-picker_time.md":"7daa9d25","lib_components_color-picker_index.md":"4df5be76","utilities_borders_utilities_border-width.md":"1b1a88bb","lib_components_datetime-picker_date.md":"21c227a0","lib_components_tabs_index.md":"bb4eff34","lib_components_button_js.md":"0e9f756e","lib_components_menu_js.md":"224426d9","lib_components_messager_index.md":"67b058f9","lib_components_btn-group_js.md":"003d2a18","lib_components_modal_js.md":"f526e803","lib_components_panel_index.md":"1b71b7e6","lib_components_contextmenu_index.md":"d45b17e6","utilities_flex_utilities_basis.md":"138dd8dd","utilities_flex_utilities_direction.md":"abebc010","lib_components_nav_index.md":"ef28bd6f","lib_components_dashboard_index.md":"dd1e11bc","lib_components_dropdown_index.md":"aac19764","lib_components_upload-imgs_index.md":"2a862036","lib_components_kanban_index.md":"e6238971","lib_forms_form_index.md":"f3abc3e4","lib_components_modal_index.md":"1a1f9348","lib_components_datetime-picker_datetime.md":"0cadce21","utilities_spacing_utilities_space.md":"9c9ea13c","utilities_flex_utilities_align-items.md":"22c1780e","lib_components_search-box_index.md":"c86b046e","lib_components_pager_js.md":"3028fad8","lib_components_toolbar_index.md":"417b7b9e","lib_components_upload_index.md":"6f7cb52d","lib_dtable_dtable_plugins.md":"0846be94","lib_components_pager_index.md":"388d302a","utilities_spacing_utilities_padding.md":"21ec4749","lib_components_table_index.md":"e2e18f9a","lib_components_toolbar_js.md":"f5c7f4c8","lib_components_menu_index.md":"8ee8d9f6","lib_components_nav_js.md":"b2dcefc8","utilities_flex_utilities_align-self.md":"40439e27","lib_helpers_core_component.md":"e09b822e","utilities_flex_utilities_justify-content.md":"6fd3f949","lib_helpers_helpers_index.md":"fd4ddadd","utilities_flex_utilities_order.md":"c23cb148","utilities_flex_utilities_shrink.md":"e66f2d89","utilities_flex_utilities_wrap.md":"96c2333a","utilities_index.md":"fa0e3981","utilities_interactivity_utilities_disabled.md":"8b659a3c","utilities_interactivity_utilities_pointer-events.md":"3610a585","utilities_interactivity_utilities_scroll.md":"770db921","utilities_interactivity_utilities_state.md":"b51b606b","utilities_interactivity_utilities_user-select.md":"8d4df33b","utilities_layout_utilities_aspect-ratio.md":"2a6f8af6","utilities_layout_utilities_container.md":"ca691f12","utilities_layout_utilities_display.md":"d06f2368","utilities_layout_utilities_floats.md":"3f189b08","utilities_layout_utilities_object-fit.md":"ffc3511e","utilities_layout_utilities_overflow.md":"ee9b6656","utilities_layout_utilities_position.md":"8bb76b9a","utilities_layout_utilities_visibility.md":"5c20a8a7","utilities_layout_utilities_z-index.md":"31cefd64","utilities_layout_utilities_top-right-bottom-left.md":"28494977","utilities_sizing_utilities_height.md":"fd41feec","utilities_sizing_utilities_width.md":"20b0b2da","utilities_spacing_utilities_margin.md":"8cb638dc","utilities_style_utilities_pale.md":"665c84b6","utilities_style_utilities_outline.md":"3a41afa0","utilities_style_utilities_solid.md":"7981ab23","utilities_typography_utilities_font-size.md":"bc50ef8d","utilities_typography_utilities_font-weight.md":"504ec9fb","utilities_typography_utilities_leading.md":"24448d06","utilities_typography_utilities_line-clamp.md":"9296b183","utilities_typography_utilities_text-align.md":"724caaab","utilities_typography_utilities_text-color.md":"ec540d0b","utilities_typography_utilities_vertical-align.md":"616176e9","utilities_typography_utilities_text-overflow.md":"68f8c500","utilities_typography_utilities_whitespace.md":"51a21ed5","utilities_typography_utilities_word-break.md":"e6bba1c1","lib_forms_checkbox_index.md":"81410693","lib_components_scrollbar_index.md":"374451a2","lib_components_tooltip_index.md":"41136a78","utilities_typography_utilities_font-family.md":"347e231c","lib_helpers_store_index.md":"192736fe","lib_icons_icons_index.md":"df8ff498","lib_index.md":"0c4894d6","public_icons_fontawesome-license.md":"93591092","themes_index.md":"2cef0f4d","utilities_backgrounds_utilities_index.md":"1fbbf90c","utilities_borders_utilities_border-color.md":"1b29fc6e","utilities_borders_utilities_border-radius.md":"f9fa136a","utilities_effects_utilities_animation.md":"82973e80","utilities_effects_utilities_filter.md":"ec0fda44","utilities_effects_utilities_flip.md":"44bcb275","utilities_effects_utilities_opacity.md":"568f5579","utilities_effects_utilities_rotate.md":"6360fe77","utilities_effects_utilities_scale.md":"3dd42b3f","utilities_effects_utilities_shadow.md":"031eb0e3","utilities_flex_utilities_align-content.md":"50208fab","lib_forms_input-control_index.md":"24c7e5f1","utilities_flex_utilities_flex.md":"b77b6d39","utilities_flex_utilities_gap.md":"f885f0e2","utilities_flex_utilities_grow.md":"f62cd68d","lib_components_progress_index.md":"4595f39f","lib_helpers_core_cash.md":"23f78ff0","lib_forms_input-group_index.md":"67dfb5c2","lib_components_label_index.md":"22af37d6","lib_dtable_dtable_index.md":"517ca7b1"} +{"guide_customize_build.md":"1d34ab5f","guide_customize_dev.md":"2553e635","frames_zui.md":"4be9ad3d","guide_config_base_color.md":"b6804a31","guide_config_base_shadow.md":"4d29d2d1","guide_config_base_font.md":"753af1aa","guide_config_base_rounded.md":"497eea65","lib_components_breadcrumb_index.md":"08e2da11","lib_components_avatar_js.md":"f77ad499","guide_customize_exts-lib.md":"2efbea3a","guide_index.md":"de433d51","guide_start_index.md":"9fbc81bf","guide_config_base_screens.md":"926a9a4b","lib_components_btn-group_js.md":"003d2a18","lib_components_avatar_index.md":"ab8fe9b0","lib_components_button_index.md":"e99c9e3f","guide_config_base_spacing.md":"20eca320","lib_forms_input-control_index.md":"24c7e5f1","lib_components_upload_index.md":"6f7cb52d","lib_helpers_core_cash.md":"23f78ff0","lib_components_toolbar_js.md":"f5c7f4c8","utilities_interactivity_utilities_scroll.md":"770db921","utilities_typography_utilities_font-weight.md":"504ec9fb","utilities_interactivity_utilities_state.md":"b51b606b","utilities_typography_utilities_font-size.md":"bc50ef8d","utilities_interactivity_utilities_user-select.md":"8d4df33b","utilities_typography_utilities_line-clamp.md":"9296b183","utilities_flex_utilities_align-content.md":"50208fab","utilities_effects_utilities_shadow.md":"031eb0e3","lib_components_progress-circle_index.md":"de2e126b","utilities_flex_utilities_align-items.md":"22c1780e","utilities_flex_utilities_align-self.md":"40439e27","lib_components_search-box_index.md":"c86b046e","utilities_flex_utilities_basis.md":"138dd8dd","utilities_flex_utilities_direction.md":"abebc010","utilities_layout_utilities_visibility.md":"5c20a8a7","utilities_typography_utilities_leading.md":"24448d06","utilities_layout_utilities_z-index.md":"31cefd64","utilities_flex_utilities_flex.md":"b77b6d39","utilities_sizing_utilities_height.md":"fd41feec","utilities_flex_utilities_gap.md":"f885f0e2","utilities_spacing_utilities_margin.md":"8cb638dc","utilities_flex_utilities_grow.md":"f62cd68d","utilities_sizing_utilities_width.md":"20b0b2da","utilities_effects_utilities_filter.md":"ec0fda44","lib_components_messager_index.md":"67b058f9","utilities_spacing_utilities_padding.md":"21ec4749","lib_components_modal_js.md":"f526e803","lib_dtable_dtable_plugins.md":"0846be94","utilities_borders_utilities_border-radius.md":"f9fa136a","utilities_backgrounds_utilities_index.md":"1fbbf90c","lib_index.md":"0c4894d6","lib_helpers_store_index.md":"192736fe","utilities_typography_utilities_word-break.md":"e6bba1c1","lib_components_tabs_index.md":"bb4eff34","lib_components_table_index.md":"e2e18f9a","lib_components_progress_index.md":"4595f39f","lib_components_button_js.md":"0e9f756e","utilities_interactivity_utilities_pointer-events.md":"3610a585","lib_components_scrollbar_index.md":"374451a2","utilities_layout_utilities_container.md":"ca691f12","lib_helpers_helpers_index.md":"fd4ddadd","lib_components_menu_index.md":"8ee8d9f6","utilities_typography_utilities_whitespace.md":"51a21ed5","utilities_typography_utilities_vertical-align.md":"616176e9","utilities_layout_utilities_overflow.md":"ee9b6656","utilities_layout_utilities_object-fit.md":"ffc3511e","public_icons_fontawesome-license.md":"93591092","lib_forms_input-group_index.md":"67dfb5c2","utilities_effects_utilities_flip.md":"44bcb275","lib_components_upload-imgs_index.md":"2a862036","utilities_layout_utilities_floats.md":"3f189b08","lib_components_menu_js.md":"224426d9","utilities_layout_utilities_display.md":"d06f2368","lib_components_color-picker_index.md":"4df5be76","utilities_layout_utilities_aspect-ratio.md":"2a6f8af6","lib_components_nav_index.md":"ef28bd6f","themes_index.md":"2cef0f4d","utilities_typography_utilities_text-color.md":"ec540d0b","lib_icons_icons_index.md":"df8ff498","utilities_typography_utilities_text-overflow.md":"68f8c500","lib_components_nav_js.md":"b2dcefc8","utilities_effects_utilities_opacity.md":"568f5579","index.md":"1a1fd727","utilities_flex_utilities_order.md":"c23cb148","lib_components_tree_index.md":"c191866d","utilities_interactivity_utilities_disabled.md":"8b659a3c","utilities_typography_utilities_text-align.md":"724caaab","utilities_effects_utilities_animation.md":"82973e80","lib_components_tooltip_index.md":"41136a78","utilities_layout_utilities_top-right-bottom-left.md":"28494977","lib_helpers_core_component.md":"e09b822e","utilities_borders_utilities_border-width.md":"1b1a88bb","lib_components_alert_index.md":"42e0e4d9","lib_components_dropdown_index.md":"aac19764","utilities_flex_utilities_justify-content.md":"6fd3f949","lib_components_contextmenu_index.md":"d45b17e6","lib_components_dashboard_index.md":"dd1e11bc","lib_dtable_dtable_index.md":"517ca7b1","utilities_effects_utilities_scale.md":"3dd42b3f","lib_components_datetime-picker_date.md":"21c227a0","lib_forms_form_index.md":"f3abc3e4","lib_forms_checkbox_index.md":"81410693","lib_components_datetime-picker_datetime.md":"0cadce21","lib_components_pager_index.md":"388d302a","lib_components_label_index.md":"22af37d6","lib_components_kanban_index.md":"e6238971","lib_components_avatar-group_index.md":"cd61e60a","utilities_typography_utilities_font-family.md":"347e231c","utilities_layout_utilities_position.md":"8bb76b9a","utilities_index.md":"fa0e3981","utilities_spacing_utilities_space.md":"9c9ea13c","lib_components_toolbar_index.md":"417b7b9e","utilities_flex_utilities_shrink.md":"e66f2d89","lib_components_pager_js.md":"3028fad8","utilities_borders_utilities_border-color.md":"1b29fc6e","utilities_style_utilities_outline.md":"3a41afa0","utilities_style_utilities_pale.md":"665c84b6","utilities_flex_utilities_wrap.md":"96c2333a","utilities_style_utilities_solid.md":"7981ab23","lib_components_btn-group_index.md":"a1a6f70b","lib_components_datetime-picker_time.md":"7daa9d25","utilities_effects_utilities_rotate.md":"6360fe77","lib_components_picker_index.md":"56bec2ee","lib_components_modal_index.md":"1a1f9348","lib_components_panel_index.md":"1b71b7e6"} diff --git a/3/index.html b/3/index.html index d9392a8fbd..1dc15333df 100644 --- a/3/index.html +++ b/3/index.html @@ -13,12 +13,12 @@ - - + +
Skip to content

ZUI3

开箱即用的组合式前端 UI 框架

100+ 组件

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/alert/index.html b/3/lib/components/alert/index.html index 3a5b6a27bf..be86b8237f 100644 --- a/3/lib/components/alert/index.html +++ b/3/lib/components/alert/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

消息框

消息框能够轻松展示一些需要引起用户注意的内容。

使用方法

使用 .alert 类来获得消息框的外观和交互体验。

Hi! 这条消息可能需要你注意。
一切已准备就绪。

注意!

可能存在潜在风险。

html
<div class="alert">Hi! 这条消息可能需要你注意。</div>
@@ -97,7 +97,7 @@
   <i class="icon icon-remove-sign alert-icon-close"></i>
   <p>右上角有关闭按钮</p>
 </div>

CSS 类

消息框提供了如下 CSS 类:

类型作用
alert实体类元素作为消息框组件
alert-icon实体类元素作为消息框内左侧图标
alert-heading实体类元素作为消息框内标题
alert-content实体类元素作为消息框内容

CSS 变量

消息框提供了如下 CSS 变量:

变量名称变量含义
--alert-radius消息框圆角
--alert-bg消息框默认背景色
--alert-text-color消息框默认文字颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/avatar-group/index.html b/3/lib/components/avatar-group/index.html index 41f394429d..60257d4cd6 100644 --- a/3/lib/components/avatar-group/index.html +++ b/3/lib/components/avatar-group/index.html @@ -15,8 +15,8 @@ - - + +
Skip to content

头像组

头像组用于将多个头像堆叠显示。

使用方法

将多个头像放置在 <div class="avatar-group"> 内即可创建一个头像组。

+10
html
<div class="avatar-group">
@@ -80,7 +80,7 @@
   <div class="avatar circle"><img src="/assets/avatar/avatar-7.png"></div>
   <div class="avatar circle gray">3.5</div>
 </div>

CSS 类

头像组提供了如下 CSS 类:

类型作用
avatar-group实体类元素作为头像组组件
size-xs工具类头像组使用超小号尺寸
size-sm工具类头像组使用小号尺寸
size-lg工具类头像组使用大号尺寸
size-xl工具类头像组使用超大号尺寸

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/avatar/index.html b/3/lib/components/avatar/index.html index ad01719c1a..675bb4f226 100644 --- a/3/lib/components/avatar/index.html +++ b/3/lib/components/avatar/index.html @@ -15,8 +15,8 @@ - - + +
Skip to content

头像

头像是用图片、图标或者文字的形式展示用户及具有特殊标识的其他对象。

使用方法

使用一个 <div> 元素并添加类 .avatar,然后将作为图像的图片、文字或图标放置在此元素内。

Z
html
<div class="avatar"><img src="/assets/avatar/avatar.png"></div>
@@ -35,7 +35,7 @@
 <div class="avatar"><img src="/assets/avatar/avatar-3.png"></div>
 <div class="avatar size-lg"><img src="/assets/avatar/avatar-4.png"></div>
 <div class="avatar size-xl"><img src="/assets/avatar/avatar-5.png"></div>

特殊用法示例

下面演示一些特殊用法。

右上角未读标签

[待定]

右下角状态标志

[待定]

CSS 类

头像提供了如下 CSS 类:

类型作用
avatar实体类元素作为头像组件
size-xs工具类头像使用超小号尺寸
size-sm工具类头像使用小号尺寸
size-lg工具类头像使用大号尺寸
size-xl工具类头像使用超大号尺寸

CSS 变量

头像提供了如下 CSS 变量,可进行全局修改:

CSS 变量名作用
--avatar-radius头像默认圆角大小
--avatar-bg头像默认背景颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/avatar/js.html b/3/lib/components/avatar/js.html index 225ca28188..ca21a5ce63 100644 --- a/3/lib/components/avatar/js.html +++ b/3/lib/components/avatar/js.html @@ -13,8 +13,8 @@ - - + +
Skip to content

头像生成器

头像生成器允许通过 JS 动态创建一个头像

示例

通过构造一个 Avatar 实例, 在一个空的 <div> 元素上创建一个头像。

文字头像

html
<div id="avatar1"></div>
@@ -39,7 +39,7 @@
 const avatar = $(element).data('zui.avatar');

更新头像

调用头像组件实例上的 render 方法来更新头像项,并重新进行渲染:

js
avatar.render({
         // ... 新的头像参数
 });

构造方法

定义:

ts
constructor(element: HTMLElement | string, options: AvatarOptions);

参数:

  • element:指定用于创建头像的容器元素,或者通过字符串指定用于查找容器元素的选择器
  • options:指定选项

示例:

ts
new zui.Avatar('#menu', options: AvatarOptions);

选项

className

类名。

  • 类型:'string' | 'object' | 'array'
  • 必选:否

size

大小。

  • 类型:'xs' | 'sm' | 'lg' | 'xl' | 'number'
  • 必选:否

circle

是否为圆形。

  • 类型:boolean
  • 必选: 否

rounded

头像圆角。

  • 类型:'boolean' | 'sm' | 'md' | 'lg' | 'number'
  • 必选:否

background

背景颜色。

  • 类型:string
  • 必选:否

foreColor

字体颜色。

  • 类型:string
  • 必选: 否

text

字体头像内容。

  • 类型:string
  • 必选:否

src

文件头像路径。

  • 类型:string
  • 必选:否

code

唯一标识,通常指定为用 ID 或 账号 组件会根据传入值生成唯一的颜色。

  • 类型:string
  • 必选:否

方法

render

重新渲染,可以指定新的选项。

定义:

ts
render(options: AvatarOptions): void;

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/breadcrumb/index.html b/3/lib/components/breadcrumb/index.html index a57a4aabae..24448f1462 100644 --- a/3/lib/components/breadcrumb/index.html +++ b/3/lib/components/breadcrumb/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

面包屑

使用方法

使用类 .breadcrumb 来实现面包屑,通常搭配 <ol><li> 元素使用。

html
<ol class="breadcrumb">
@@ -22,7 +22,7 @@
   <li><a href="your/url/">图书馆</a></li>
   <li class="active">数据</li>
 </ol>

CSS 类

面包屑提供了如下CSS类

类型作用
breadcrumb实体类元素作为面包屑组件

CSS 变量

变量名称变量含义
--breadcrumb-divider面包屑分割元素标签类型
--breadcrumb-divider-color面包屑分割元素颜色
--breadcrumb-color-active面包屑选中态元素颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/btn-group/index.html b/3/lib/components/btn-group/index.html index e1e6781b68..92786c161b 100644 --- a/3/lib/components/btn-group/index.html +++ b/3/lib/components/btn-group/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

按钮组

按钮组可以将多个按钮成组展示。

使用方法

将多个 按钮 放置在 <div class="btn-group"> 内即可创建一个按钮组。

html
<div class="btn-group">
@@ -125,7 +125,7 @@
     </div>
   </div>
 </div>

CSS 类

按钮提供了如下 CSS 类:

类型作用
btn-group实体类元素作为按钮组组件
size-xs工具类按钮组使用超小号尺寸
size-sm工具类按钮组使用小号尺寸
size-lg工具类按钮组使用大号尺寸
size-xl工具类按钮组使用超大号尺寸
disabled工具类.btn 一起使用,标记按钮为禁用状态

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/btn-group/js.html b/3/lib/components/btn-group/js.html index ae4214560c..176d6a254e 100644 --- a/3/lib/components/btn-group/js.html +++ b/3/lib/components/btn-group/js.html @@ -13,8 +13,8 @@ - - + +
Skip to content

按钮组生成器

常用于多项按钮操作的组件,通过 JS 动态生成,使用时方便快捷。

使用方法

html
<div id="btnGroup"></div>
@@ -113,7 +113,7 @@
         {text: '剪切'},
     ],
 });

选项

className

类名。

  • 类型:string
  • 必选:否

btnProps

继承 按钮属性

items

size

按钮尺寸。

  • 类型:string
  • 可选项: xs | sm | lg | xl
  • 必选:否

type

按钮组类型。

  • 类型:string
  • 必选:否

itemRender

指定一个回调函数用于对组件渲染进行自定义。

参数items 选项的单个配置;

返回值items 选项的单个配置。

beforeRender

指定一个回调函数在渲染之前调用,可重新配置组件选项。

参数:用户为按钮组组件件设置的 options

返回值:组件选项数据。

afterRender

指定一个回调函数在渲染之后调用。

参数:

  • firstRender:判断是否第一次渲染;
  • menu:组件信息。

beforeDestroy

指定一个回调函数在组件销毁之前调用,无参数。

API

btnProps

按钮组子项属性:

ts
type BtnProps = ButtonProps & {key?: string | number | symbol};

继承按钮组件 ButtonProps属性,同时添加了 key 属性。

key

指定单个按钮键值,用户可根据该属性进行特殊处理。

  • 类型:string | number | symbol
  • 必选:否。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/button/index.html b/3/lib/components/button/index.html index a1c6b85b4e..f94ba19a4f 100644 --- a/3/lib/components/button/index.html +++ b/3/lib/components/button/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

按钮

按钮是用来触发一些动作。通常用在表单、对话框、菜单上面。好的按钮设计能够引导用户高效的达到目的。

使用方法

使用 .btn 类来获得按钮的外观和交互体验,通常用在元素 <button><a> 上。

html
<button type="button" class="btn">按钮</button>

配合丰富的CSS 工具类来实现不同按钮的外观。

html
<button type="button" class="btn primary">主要按钮</button>
@@ -139,7 +139,7 @@
   <i class="spin icon icon-spinner-snake"></i>
   加载中
 </button>

CSS 类

按钮提供了如下 CSS 类:

类型作用
btn实体类元素作为按钮组件
square工具类按钮使用正方形外观
size-xs工具类按钮使用超小号尺寸
size-sm工具类按钮使用小号尺寸
size-lg工具类按钮使用大号尺寸
size-xl工具类按钮使用超大号尺寸

CSS 变量

变量名称变量含义
--btn-radius按钮圆角
--btn-bg按钮背景颜色
--btn-border-color按钮边框颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/button/js.html b/3/lib/components/button/js.html index 23866f65b0..3e17e9a78e 100644 --- a/3/lib/components/button/js.html +++ b/3/lib/components/button/js.html @@ -13,8 +13,8 @@ - - + +
Skip to content

按钮生成器

按钮生成器是通过 JS 动态生成的按钮组件,用来触发一些动作。通常用在表单、对话框、菜单上面。

使用方法

基础的按钮用法。

html
<div id="btnExp"></div>
@@ -92,7 +92,7 @@
 new zui.Button('#showBtn4', {text: '编辑', type: 'primary-pale'});
 new zui.Button('#showBtn5', {text: '删除', type: 'danger-pale'});
 </script>

选项

按钮的属性。

text

标题。

  • 类型:string
  • 必选:否。

icon

左侧图标。

  • 类型:string | VNode
  • 必选:否。

trailingIcon

右侧图标。

  • 类型:string | VNode
  • 必选:否。

hint

按钮鼠标悬浮提示文案。

  • 类型:string
  • 必选:否;

component

标签类型,通常会使用 <a> 标签或者 <button> 标签,也可以用 <div>

  • 类型:string | ComponentType
  • 必选:否。

type

按钮的外观类型。

  • 类型:string
  • 必选:否;
  • 可选项:'primary', 'secondary' ...,具体可参考 CSS 工具类 中的样式。

size

按钮的尺寸

  • 类型:string
  • 必选:否;
  • 可选项:'xs' | 'sm' | 'lg' | 'xl'

className

类名。

  • 类型:string
  • 必选:否。

style

样式。

  • 类型:ClassNameLike
  • 必选:否。

url

跳转链接地址;前提按钮标签类型只能为 <a> 标签。

  • 类型:string
  • 必选:否。

target

在何处打开链接地址;前提按钮标签类型只能为 <a> 标签。

disabled

是否禁用。

  • 类型:boolean
  • 必选:否;
  • 默认: false

active

是否是激活状态。

  • 类型:boolean
  • 必选:否;
  • 默认: false

loading

加载中状态。

  • 类型:boolean
  • 必选:否;
  • 默认: false

loadingIcon

加载中状态的图标。

  • 类型:string
  • 必选:否;

loadingText

加载中状态的文案。

  • 类型:string
  • 必选:否;

square

是否展示为正方形。

  • 类型:boolean
  • 必选:否;
  • 默认: true

caret

按钮展示箭头。

  • 类型:string | boolean
  • 必选:否;
  • 可选项:'up' | 'down' | 'left' | 'right' | boolean
  • 默认: false

onClick

鼠标点击的回调方法。

  • 类型:function
  • 必选:否。

children

子元素。

  • 类型:ComponentChildren | (() => ComponentChildren)
  • 必选:否。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/color-picker/index.html b/3/lib/components/color-picker/index.html index ebdf7f3ad1..888bc0e9cb 100644 --- a/3/lib/components/color-picker/index.html +++ b/3/lib/components/color-picker/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

颜色选择器

基于下拉选择器实现的颜色选择器。

基本使用

在选定元素上调用初始化函数即可使用颜色选择器。

html
<div id="color-picker-1"></div>
JavaScript
const colorPicker = new ColorPicker('#color-picker-1', {
@@ -106,7 +106,7 @@
     /** 弹出面板的标题。 */
     heading?: ComponentChildren;
 }

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/contextmenu/index.html b/3/lib/components/contextmenu/index.html index 236774fb27..d31babc2b9 100644 --- a/3/lib/components/contextmenu/index.html +++ b/3/lib/components/contextmenu/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

上下文菜单

自定义鼠标右击动态生成菜单。

使用方法

鼠标右击时,展开更多操作, 在响应的区域添加 data-toggle="contextmenu"

静态用法

在此区域使用右键菜单
html
<div class="w-full h-32 primary-pale row items-center justify-center" data-toggle="contextmenu">
@@ -112,7 +112,7 @@
     });
 });
 </script>

API

items 的单个对象属性

text

名称。

  • 类型:string
  • 必选:否。

icon

左侧图标。

  • 类型:string
  • 必选:否。

trailingIcon

右侧图标。

  • 类型:string | VNode
  • 必选:否。

className

类名。

  • 类型:string
  • 必选:否。

style

样式。

  • 类型:ClassNameLike
  • 必选:否。

url

跳转链接地址。

  • 类型:string
  • 必选:否。

target

在何处打开链接地址。

  • 类型:string
  • 必选:否;
  • 可选项: _self | _self | _black | _top | _parent

disabled

是否禁用。

  • 类型:boolean
  • 必选:否;
  • 默认: false

active

是否是激活状态。

  • 类型:boolean
  • 必选:否;
  • 默认: false

type

单项类型。

  • 类型:string
  • 必选:否;
  • 可选项:item | divider | heading | custom
  • 默认: item

rootClass

menu-item 同级类名。

  • 类型:string
  • 必选:否。

items

子级操作数据。

  • 类型:array
  • 必选:否。

onClick

点击操作菜单项的回调事件。

  • 类型:function
  • 必选:否。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/dashboard/index.html b/3/lib/components/dashboard/index.html index f7b0ef255c..7ef6c06ba2 100644 --- a/3/lib/components/dashboard/index.html +++ b/3/lib/components/dashboard/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

仪表盘

仪表盘用于创建由多个区块构成的信息展示页面,这些区块可以灵活排练,可以是图表、表格、卡片等。

用法

一般用法

html
<div id="dashboardExample"></div>
@@ -79,7 +79,7 @@
     blockMenu?: ContextMenuOptions;
     onLayoutChange?: (blocks: BlockSetting[]) => void;
 };

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/datetime-picker/date.html b/3/lib/components/datetime-picker/date.html index 086ee01a34..b5208acfbf 100644 --- a/3/lib/components/datetime-picker/date.html +++ b/3/lib/components/datetime-picker/date.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/datetime-picker/datetime.html b/3/lib/components/datetime-picker/datetime.html index f58d64a6ba..8e401d02a8 100644 --- a/3/lib/components/datetime-picker/datetime.html +++ b/3/lib/components/datetime-picker/datetime.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/datetime-picker/time.html b/3/lib/components/datetime-picker/time.html index 17bc883539..d5f87e6137 100644 --- a/3/lib/components/datetime-picker/time.html +++ b/3/lib/components/datetime-picker/time.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/dropdown/index.html b/3/lib/components/dropdown/index.html index 32663de365..eb2bf8dbc2 100644 --- a/3/lib/components/dropdown/index.html +++ b/3/lib/components/dropdown/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

下拉菜单

将动作或菜单折叠到下拉菜单中。

使用方法

点击按钮,展开更多操作。如需默认展开,可在 .dropdown 类上添加 .open

html
<button class="btn" type="button" data-toggle="dropdown">菜单按钮 <span class="caret"></span></button>
@@ -82,7 +82,7 @@
     <li class="menu-heading">更多操作</li>
     <li class="menu-item"><a>修改</a></li>
 </menu>

CSS 类

按钮提供了如下 CSS 类:

类型作用
dropdown实体类元素作为下拉菜单组件
dropdown-menu实体类元素作为下拉菜单列表
dropdown-header实体类元素作为下拉菜单中的标题
dropdown-submenu实体类元素作为下拉菜单子菜单列表
caret实体类元素作为下拉菜单icon图标
dropup工具类下拉框浮动方向为上方
menu-align-right工具类下拉框展开后右侧对齐
expand-left工具类子菜单左侧显示

CSS 变量

变量名称变量含义
--dropmenu-radius下拉菜单圆角
--dropmenu-border-color下拉菜单边框颜色
--dropmenu-bg下拉菜单背景颜色
--dropmenu-active-color下拉菜单条目激活状态文字颜色
--dropmenu-active-bg下拉菜单条目激活状态背景颜色

API

操作菜单定义对象。

trigger

触发方式

  • 类型:click | hover | manual
  • 必选:否。

arrow

箭头大小 为 true 则为默认12

  • 类型:boolean | number
  • 必选:否。

offset

偏移量

  • 类型:number
  • 必选:否。

菜单对象 详细配置可参考 菜单

  • 类型:object
  • 必选:否。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/kanban/index.html b/3/lib/components/kanban/index.html index 8e22f69ce8..4451daf4f0 100644 --- a/3/lib/components/kanban/index.html +++ b/3/lib/components/kanban/index.html @@ -13,12 +13,12 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/label/index.html b/3/lib/components/label/index.html index a4d6178f39..c0b9555421 100644 --- a/3/lib/components/label/index.html +++ b/3/lib/components/label/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

标签

标签是用来触发一些动作。通常用在表单、对话框、菜单上面。好的标签设计能够引导用户高效的达到目的。

使用方法

使用 .label 类来获得标签的外观和交互体验,通常用在元素 <span> 上。

标签
html
<span class="label">标签</span>

配合丰富的CSS 工具类来实现不同标签的外观。

主要标签黑色标签描边
html
<span class="label primary">主要标签</span>
@@ -92,7 +92,7 @@
 <span class="label label-dot light"></span>
 <span class="label label-dot gray"></span>
 <span class="label label-dot dark"></span>

与按钮组合使用

html
<button class="btn" type="button">按钮 <span class="label sm rounded-full">12</span></button>

CSS 类

标签提供了如下 CSS 类:

类型作用
label实体类元素作为标签组件
label-dot工具类标签使用圆形外观
size-sm工具类标签使用小号尺寸
size-lg工具类标签使用大号尺寸

CSS 变量

变量名称变量含义
--label-bg标签背景色
--label-color标签文字颜色
--label-border-color标签边框颜色
--label-radius标签圆角

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/menu/index.html b/3/lib/components/menu/index.html index 081a7e6f72..9f85619ef2 100644 --- a/3/lib/components/menu/index.html +++ b/3/lib/components/menu/index.html @@ -14,8 +14,8 @@ - - + +
Skip to content

菜单

菜单用于展示一个操作列表,也可以用于构建更复杂的组件,例如右键菜单、下拉菜单等。如果需要通过 JS 动态创建菜单,可以使用菜单生成器

导入

如果你使用的是非合并打包版本,可以通过如下方式单独引入菜单的 CSS 样式:

js
import 'zui/menu/css';

使用方法

使用类 .menu.menu-item 按照如下结构来构建一个静态菜单:

html
<menu class="menu w-32">
@@ -68,7 +68,7 @@
   <li class="menu-divider"></li>
   <li class="text-danger menu-item"><a href="#">退出</a></li>
 </menu>

CSS 类

头像提供了如下 CSS 类:

类型作用
menu实体类元素作为菜单
menu-item实体类元素作为菜单项
menu-heading实体类元素作为菜单标题
menu-divider实体类元素作为分割线
has-icons工具类menu 一起使用,标记菜单内包含图标
active工具类menu-item 一起使用,标记菜单项为激活状态
disabled工具类menu-item 一起使用,标记菜单项为禁用状态

CSS 变量

头像提供了如下 CSS 变量,可进行全局修改:

CSS 变量名作用默认值
--menu-radius菜单圆角var(--radius)
--menu-bg菜单背景颜色var(--color-canvas)
--menu-border菜单边框1px solid var(--color-border)
--menu-shadow菜单阴影var(--shadow-lg)
--menu-hover-bg菜单项鼠标悬停背景色var(--color-primary-500)
--menu-hover-color菜单项鼠标悬停文字颜色var(--color-canvas)
--menu-active-bg菜单项激活状态背景色var(--color-primary-50)
--menu-active-color菜单项激活状态文字颜色var(--color-primary-500)
--menu-icon-opacity菜单项图标透明度.5
--menu-heading-color菜单标题文字颜色var(--color-gray-500)

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/menu/js.html b/3/lib/components/menu/js.html index 9fe8e9ea95..d9ab043ba1 100644 --- a/3/lib/components/menu/js.html +++ b/3/lib/components/menu/js.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/messager/index.html b/3/lib/components/messager/index.html index d7d50407f4..301012a66d 100644 --- a/3/lib/components/messager/index.html +++ b/3/lib/components/messager/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

漂浮消息生成器

通过 JS 动态创建一个漂浮消息。

基本用法

通过构造一个 messager 实例,页面上创建一个漂浮消息。

js
button.addEventLinstener('click', function() {
@@ -43,7 +43,7 @@
         }
     }]
 });

禁用自动隐藏

默认超过 5000ms 自动隐藏,通过设置 time0 取消自动隐藏。

禁用动画效果

设置 animationfalse 禁用动画效果。

API

MessagerOptions

漂浮消息定义对象。

type

消息类型

  • 类型:string;
  • 可选值:'default' | 'primary' | 'danger' | 'success' | 'warning' | 'important' | 'special';
  • 必选:否。
  • 默认值:default

placement

漂浮消息定位方式

  • 类型:string;
  • 可选值:'top' | 'center' | 'bottom' | 'left-top' | 'left' | 'left-bottom' | 'right' | 'right-top' | 'right-bottom';
  • 必选:否。
  • 默认值:top

time

漂浮消息持续时间。

  • 类型:number;
  • 必选:否。
  • 默认值:4000 (ms);

message

漂浮消息内容。

  • 类型:string;
  • 必选:否。

parent

漂浮消息父节点。

  • 类型:HTMLElement;
  • 必选:否。
  • 默认值:body.

icon

图标内容。

  • 类型:string;
  • 必选:否。

close

是否展示关闭按钮。

  • 类型:boolean;
  • 必选:否。
  • 默认值:false。

show

是否在初次渲染时展示消息。

  • 类型:boolean;
  • 必选:否。
  • 默认值:true。

fade

是否显示和隐藏消息时使用渐隐渐显的动画效果。

  • 类型:boolean;
  • 必选:否。
  • 默认值:false。

scale

是否显示和隐藏消息时使用缩放的动画效果。

  • 类型:boolean;
  • 必选:否。
  • 默认值:false。

actions 漂浮消息按钮组配置项,详细配置可参考 按钮组

onAction

  • 类型:function(actionName, action, messager);
  • 必选:否。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/modal/index.html b/3/lib/components/modal/index.html index 7249981385..f368d50594 100644 --- a/3/lib/components/modal/index.html +++ b/3/lib/components/modal/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

对话框

在保留当前页面状态的情况下,直接使用触发按钮即可展现对话框,告知用户展示相关操作。

使用方法

使用 .modal.modal-dialog 类获得对话框的外观展示,通常用在元素 <div> 上。

点击 a 标签按钮打开
html
<button type="button" class="btn primary" data-toggle="modal" data-target="#myModal">
@@ -136,7 +136,7 @@
     </div>
   </div>
 </div>

CSS 类

对话框提供了如下 CSS 类:

类型作用
modal实体类元素作为对话框遮罩组件
modal-dialog实体类元素作为对话框组件
size-sm工具类对话框使用小号尺寸
size-lg工具类对话框使用大号尺寸

CSS 变量

对话框提供了如下 CSS 变量,可进行全局修改。

CSS 变量名作用
--modal-radius对话框默认圆角大小
--modal-bg对话框遮挡层颜色
--modal-sm对话框小号尺寸宽度
--modal-base对话框默认宽度
--modal-lg对话框大号尺寸宽度

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/modal/js.html b/3/lib/components/modal/js.html index e836752eda..d6230c02da 100644 --- a/3/lib/components/modal/js.html +++ b/3/lib/components/modal/js.html @@ -13,8 +13,8 @@ - - + +
Skip to content

对话框触发器

对话框触发器允许你不需要书写静态对话框HTML,直接使用触发按钮或者一行Javascript代码即可让一个全新的对话框展现。支持使用Ajax从远程获取内容,或者通过iframe加载任何页面内容,当然不使用远程内容,直接使用本地内容也是很方便。

iframe 对话框

html
<button type="button" class="btn primary" data-toggle="modal" data-url="/lib/modal/dev/iframe-modal.html" data-title="iframe 对话框">点击打开 iframe 对话框</button>

Ajax 对话框

html
<button type="button" class="btn primary" data-toggle="modal" data-type="ajax" data-url="/lib/modal/dev/ajax-modal.html" data-title="Ajax HTML 对话框" data-data-type="html">点击打开 Ajax HTML 对话框</button>

自定义信息提示弹窗

html
<button type="button" class="btn primary" data-toggle="modal" data-title="自定义对话框" data-content="这里是对话框内容">点击打开自定义对话框</button>

模态框

通过 data-backdrop="false" 动态控制,设置后可以操作模态框之外的交互。

html
<button type="button" class="btn primary" data-backdrop="false" data-toggle="modal" data-title="自定义对话框" data-content="这里是对话框内容">点击打开模态对话框</button>

系统对话框

警告框

通过 Modal.alert() 方法可以打开一个警告框,该方法定义如下:

ts
/* 直接指定要提示的消息文本 */
@@ -70,7 +70,7 @@
 >
   Modal.confirm(options)
 </button>

选项

className

类名。

  • 类型:string
  • 必选:否。

style

样式。

  • 类型:JSX.CSSProperties
  • 必选:否。

size

尺寸大小。

  • 类型:'sm' | 'lg' | 'md' | 'full' | number | {width: number, height: number};
  • 必选:否。

position

位置。

  • 类型:'fit' | 'center' | 'bottom' | 'top' | number | {left: number, top: number, width: number, height: number}
  • 必选:否;
  • 默认:fit

backdrop

是否启用背景遮罩。

  • 类型:'static' | boolean
  • 必选:否;
  • 默认:true

show

是否展示弹窗

  • 类型:boolean
  • 必选:否;
  • 默认:true

keyboard

是否启用按键关闭对话框。

  • 类型:boolean
  • 必选:否;
  • 默认:true

moveable

是否可移动。

  • 类型:boolean
  • 必选:否;
  • 默认:false

animation

是否启用动画效果。

  • 类型:boolean
  • 必选:否;
  • 默认:true

transTime

过渡时间。

  • 类型:number
  • 必选:否;
  • 默认:300

responsive

是否自使用。

  • 类型:boolean
  • 必选:否;
  • 默认:true

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/nav/index.html b/3/lib/components/nav/index.html index 577ad920bd..9a6e936d88 100644 --- a/3/lib/components/nav/index.html +++ b/3/lib/components/nav/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

导航

使用方法

使用组件类.nav来获得导航外观 通常搭配<ul>,<li> 标签来使用

基础样式

html
<menu class="nav">
@@ -82,7 +82,7 @@
 </menu>
 
 ...

带分隔线的导航

CSS 类

导航提供了如下CSS类

类型作用
nav实体类元素导航组件
nav-heading实体类导航标题组件
nav-divider实体类导航分割线组件
active工具类为导航元素启用选中态样式
nav-simple工具类为导航元素启用简单样式
nav-primary工具类为导航元素启用主要导航样式
nav-secondary工具类为导航元素启用次要导航样式
nav-tabs工具类为导航元素启用标签风格导航样式
nav-pills工具类为导航元素启用标签风格导航样式
nav-stacked工具类为导航元素启用垂直排列导航样式
nav-justified工具类为导航元素启用自适应宽度导航样式

CSS 变量

变量名称变量含义
--nav-radius导航圆角大小
--nav-border-color导航边框颜色
--nav-secon-border-color次要导航边框颜色
--nav-heading-bg-color导航标题背景颜色
--nav-heading-color导航标题字体颜色
--nav-heading-color导航标题字体颜色
--nav-divider-color导航分隔线颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/nav/js.html b/3/lib/components/nav/js.html index e10ccacdd3..145bb62c16 100644 --- a/3/lib/components/nav/js.html +++ b/3/lib/components/nav/js.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/pager/index.html b/3/lib/components/pager/index.html index d0b1266907..f1989b7b24 100644 --- a/3/lib/components/pager/index.html +++ b/3/lib/components/pager/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

分页

当数据量过多时,使用分页的形式分解数据。

使用方法

将多个按钮放置在 <div class="pager"> 内即可创建一个分页组件。

html
<nav class="gap-1 pager">
@@ -159,7 +159,7 @@
     ...
   </menu>
 </div>

CSS 类

分页提供了如下 CSS 类:

类型作用
pager实体类元素作为分页组件
pager-goto实体类元素作为分页的跳转组件
pager-size-menu实体类元素作为分页的每页条数的下拉组件

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/pager/js.html b/3/lib/components/pager/js.html index 0ea299cd3b..82a1117b1e 100644 --- a/3/lib/components/pager/js.html +++ b/3/lib/components/pager/js.html @@ -13,8 +13,8 @@ - - + +
Skip to content

分页生成器

当数据量过多时,使用分页生成器动态分解数据。

综合用法

html
<div id="pagerExample1"></div>
@@ -164,7 +164,7 @@
 render(element, <Pager {...options} />);

使用Jquery 扩展

js
$(element).pager(options);
 
 const pager = $(element).data('zui.pager');

选项

linkCreator

导航链接生成器,点击页码时进行页面地址更换。

  • 类型:string | ((info: PagerInfo) => string)
  • 必选:否

page

初始状态的当前页码。

  • 类型:number

recTotal

总记录数目。

  • 类型:number

recPerPage

每页记录数。

  • 类型:number

pageTotal

总页数。

  • 类型:number

items

定义分页项的列表,可以通过一个函数动态返回分页组件。

基于 工具栏 选项 和 自定义 PagerItemOptions 选项。

onClickItem

指定分页按钮的点击回调事件。

API

PagerInfo

参数:

page

  • 含义:初始状态的当前页码;
  • 类型:number

recTotal

  • 含义:总记录数目;
  • 类型:number

recPerPage

  • 含义:每页记录数;
  • 类型:number

pageTotal

  • 含义:总页数;
  • 类型:number

PagerItemOptions

参数:

type

  • 含义:子项类型;
  • 类型:string
  • 可选项:info | link | nav | size-menu | goto

page

  • 含义:页码名称;
  • 类型:'first' | 'last' | 'prev' | 'next' | 'current' | number

text

  • 含义:指定类型为 info | size-menu 的显示文案;
  • 类型:string | ((info: PagerInfo) => string)

count

  • 含义:指定类型为 nav 的展示数量;
  • 类型:number

format

  • 含义:指定类型为 link | nav 的显示格式;
  • 类型:string | ((info: PagerInfo) => string)
  • 含义:指定下拉菜单的属性;
  • 类型:object

items

  • 含义:指定类型为 size-menu 下拉菜单里的选项;
  • 类型:number[]

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/panel/index.html b/3/lib/components/panel/index.html index 6cee2d93e6..69b95dbc08 100644 --- a/3/lib/components/panel/index.html +++ b/3/lib/components/panel/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

面板

可以将某些DOM内容放在面板组件中。

基本使用

一个面板通常包含标题,内容,脚注三部分。标题,脚注可按需选择使用。

面板标题
面板内容
html
<div class="panel">
@@ -134,7 +134,7 @@
     </div>
     <div class="panel-body">内容</div>
   </div>

CSS 类

面板提供了如下 CSS 类:

类型作用
panel实体类元素作为面板组件

CSS 变量

面板提供了如下 CSS 变量:

变量名称变量含义
--panel-heading-bg标题背景色
--panel-heading-color标题文字颜色
--panel-footer-bg脚注背景色
--panel-border-color面板边框颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/picker/index.html b/3/lib/components/picker/index.html index 79c6fb6d65..4a67acbca6 100644 --- a/3/lib/components/picker/index.html +++ b/3/lib/components/picker/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

下拉选择器

用于方便用户从多个选项列表中进行选择。

单选

html
<div id="singlePickerExample"></div>
@@ -220,7 +220,7 @@
     /** 样式。 */
     style?: JSX.CSSProperties;
 }

本地列表项

通过初始化选项 items 指定为一个选项对象数组来定义本地列表项。

异步获取列表项

通过初始化选项 items 指定为一个回调函数来返回列表项,可以直接返回选项对象数组,或者通过 Promise 异步返回。

远程获取列表项

[WIP]

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/progress-circle/index.html b/3/lib/components/progress-circle/index.html index c1889b26b4..01ea0fe59d 100644 --- a/3/lib/components/progress-circle/index.html +++ b/3/lib/components/progress-circle/index.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/progress/index.html b/3/lib/components/progress/index.html index acc636fd21..6867469d1e 100644 --- a/3/lib/components/progress/index.html +++ b/3/lib/components/progress/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

进度条

使用方法

使用实体类 progressprogress-bar 应用进度条CSS组件。

html
<div class="progress">
@@ -37,7 +37,7 @@
    <div class="progress-bar success" style="width: 40%"></div>
    <label class="ml-4">40%</label>
  </div>

CSS 类

进度条提供了如下 CSS 类

类型作用
progress实体类元素作为进度条容器组件
progress-bar实体类元素作为进度条组件
progress-striped工具类为进度条组件启用条纹样式
active工具类为条纹样式进度条组件启用动画效果

CSS变量

变量名称变量含义
--progress-bg进度条组件背景颜色
--progress-bar-color进度条组件颜色
--progress-radius进度条组件圆角大小
--progress-striped-size进度条组件条纹大小

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/scrollbar/index.html b/3/lib/components/scrollbar/index.html index 9448f9b56c..bda0bff326 100644 --- a/3/lib/components/scrollbar/index.html +++ b/3/lib/components/scrollbar/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

滚动条

滚动条样式

Lorem ipsum dolor sit amet consectetur adipisicing elit. Veniam, accusamus.Molestiae saepe deleniti voluptas excepturi nostrum. Consequatur eius non voluptates!Commodi omnis minus quo totam, ab aspernatur sequi vero cum?

Explicabo asperiores recusandae qui? Aliquam similique eaque animi nemo? Fugiat.Cupiditate eaque, doloribus magnam velit ipsum maiores voluptatum eveniet rem!

Pariatur sapiente laboriosam cumque itaque, id saepe commodi accusantium neque?

Cupiditate eaque, doloribus magnam velit ipsum maiores voluptatum eveniet rem!

Quidem eum, reiciendis iusto rem perspiciatis neque optio! Quae, sint!

Maxime animi iure enim sint aperiam tempora non voluptatibus dolore.

Suscipit cumque minus veritatis labore dolor corporis molestias. Rem, pariatur.

Commodi omnis minus quo totam, ab aspernatur sequi vero cum?

Repellendus rerum tempora eos praesentium at placeat, quas quibusdam sunt?

Molestiae saepe deleniti voluptas excepturi nostrum. Consequatur eius non voluptates!

html
<div style="height: 100px; overflow: scroll; white-space: nowrap">
@@ -26,7 +26,7 @@
 </div>

CSS scrollbar with overflow=overlay

Lorem ipsum dolor sit amet consectetur adipisicing elit. Veniam, accusamus.Molestiae saepe deleniti voluptas excepturi nostrum. Consequatur eius non voluptates!Commodi omnis minus quo totam, ab aspernatur sequi vero cum?

Explicabo asperiores recusandae qui? Aliquam similique eaque animi nemo? Fugiat.Cupiditate eaque, doloribus magnam velit ipsum maiores voluptatum eveniet rem!

Pariatur sapiente laboriosam cumque itaque, id saepe commodi accusantium neque?

Cupiditate eaque, doloribus magnam velit ipsum maiores voluptatum eveniet rem!

Quidem eum, reiciendis iusto rem perspiciatis neque optio! Quae, sint!

Maxime animi iure enim sint aperiam tempora non voluptatibus dolore.

Suscipit cumque minus veritatis labore dolor corporis molestias. Rem, pariatur.

Commodi omnis minus quo totam, ab aspernatur sequi vero cum?

Repellendus rerum tempora eos praesentium at placeat, quas quibusdam sunt?

Molestiae saepe deleniti voluptas excepturi nostrum. Consequatur eius non voluptates!

html
<div style="overflow: overlay; height: 100px; white-space: nowrap">
   ...
 </div>

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/search-box/index.html b/3/lib/components/search-box/index.html index 13a43bf796..3956eaf381 100644 --- a/3/lib/components/search-box/index.html +++ b/3/lib/components/search-box/index.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/table/index.html b/3/lib/components/table/index.html index 282c667bef..e44f5d176f 100644 --- a/3/lib/components/table/index.html +++ b/3/lib/components/table/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

表格

表格用于展示二维数据。

使用方法

<table> 元素添加 CSS 类 .table 来使用表格。

组成部分元素标签说明
表头<thead>表头通常作为表格第一行,用于展示所有数据的各个属性名称。
主体<tbody>一个或多个行组成表格的主体,每行用于展示一个数据。
表尾<tfoot>表尾通常用于展示一些数据的汇总信息。
总计3 个部分
html
<table class="table">
@@ -98,7 +98,7 @@
     </tr>
   </tbody>
 </table>

CSS 类

按钮提供了如下 CSS 类:

类型作用
table实体类元素作为表格组件
table-striped工具类为表格启用斑马纹效果
table-hover工具类为表格启用行悬停变色效果
table-fixed工具类为表格启用固定布局
borderless工具类移除表格所有边框
bordered工具类为表格添加完整边框
condensed工具类为表格启用紧凑布局

CSS 变量

变量名称变量含义
--table-head-bg表头背景色
--table-striped-color表格斑马纹行背景色
--table-hover-color表格行响应鼠标悬停变化背景颜色
--table-border-color表格边框颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/tabs/index.html b/3/lib/components/tabs/index.html index ec964057a1..892a21d760 100644 --- a/3/lib/components/tabs/index.html +++ b/3/lib/components/tabs/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

标签页

标签页允许通过点击一个导航或列表项目来切换显示的内容。
标签页内容使用 .tab-pane 作为容器元素,所有供切换显示的 .tab-pane 放置在 .tab-content 容器元素内。
为确保在页面显示的时候标签页能够指示正确的标签和显示正确的内容,在初始状态需要为当前选中的导航项目 li.nav-item>a 元素添加 .active 类,并且为当前显示的标签页内容元素 .tab-pane 添加 .active 类。

使用方法

为导航上每个用于切换标签内容的链接添加 hrefdata-target 属性指向当前标签页内容的 id ,并添加 data-toggle="tab" 属性。 -accent-inverse

我是标签1。

我是标签2。

我是标签3。

html
<ul class="nav nav-tabs">
@@ -116,7 +116,7 @@
   console.log('>', event.type, info);
 });
 </script>

CSS类

标签页提供了如下 CSS 类:

类型作用
tab-content实体类元素作为所有标签页容器
tab-pane实体类元素作为单独的标签页容器
fade工具类标签页使用渐变动画效果
in工具类标签页使用渐变动画效果,和 fade 同时使用

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/toolbar/index.html b/3/lib/components/toolbar/index.html index 4c553c372c..8ba5780b70 100644 --- a/3/lib/components/toolbar/index.html +++ b/3/lib/components/toolbar/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

工具栏

使用方法

html
<nav class="toolbar">
@@ -106,7 +106,7 @@
   <div class="toolbar-space" style="flex: 1 1 0%;"></div>
   <button class="btn ghost square" title="添加" type="button"><i class="icon icon-check-plus"></i></button>
 </nav>

CSS 类

头像提供了如下 CSS 类:

类型作用
toolbar实体类元素作为工具栏
toolbar-divider实体类元素作为分割线
toolbar-space实体类元素作为工具栏项之前的间距

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/toolbar/js.html b/3/lib/components/toolbar/js.html index 5f366b37cf..e50ec4dd25 100644 --- a/3/lib/components/toolbar/js.html +++ b/3/lib/components/toolbar/js.html @@ -13,8 +13,8 @@ - - + +
Skip to content

工具栏生成器

基于操作菜单 操作菜单 实现的组件,与特定的功能关联起来使用,跟导航类似,但比导航更轻量更灵活。

使用方法

html
<div id="toolbarExp"></div>
@@ -149,7 +149,7 @@
 render(element, <Toolbar {...options} />);

使用 jQuery 扩展

js
$(element).toolbar(options);
 
 const toolbar = $(element).data('zui.toolbar');

选项

操作菜单 选项基础上添加新的参数选项。

wrap

限制工具栏按钮过多超出时是否换行。

  • 类型:boolean
  • 必选:否;
  • 默认值:false

gap

自定义工具栏按钮的间距,与 .toolbar 同级生成 .gap-* 的工具类控制按钮间距。

  • 类型:number | string
  • 必选:否

items

继承了 操作菜单 选项和按钮选项,同时添加了其他选项。

btnProps

继承按钮组件的属性, 统一处理工具栏按钮属性外观等。

itemRender

指定一个回调函数用于对组件渲染进行自定义。

参数items 选项的单个配置;

返回值items 选项的单个配置。

beforeRender

指定一个回调函数在渲染之前调用,可重新配置组件选项。

参数:用户为按钮组组件件设置的 options

返回值:组件选项数据。

afterRender

指定一个回调函数在渲染之后调用。

参数:

  • firstRender:判断是否第一次渲染;
  • menu:组件信息。

beforeDestroy

指定一个回调函数在组件销毁之前调用,无参数。

API

ToolbarItemOptions

ts
type ToolbarItemOptions = ToolbarItemProps | ToolbarDropdownProps | ToolbarBtnGroupProps | ToolbarDividerProps | ToolbarSpaceProps;

ToolbarItemProps

选项:

继承了操作菜单的 ActionItemProps 选项和按钮的 ButtonProps ,同时添加了其他选项 btnType,用来设置按钮外观类型。

btnType

设置工具栏单个按钮的外观类型。

  • 类型:string
  • 必选:否。

ToolbarDropdownProps

选项:

在原有属性基础上固定 type 属性,并继承了下拉菜单的 DropdownButtonOptions 选项,同时添加了其他选项。

type
  • 类型:string
  • 属性值:dropdown
  • 必选:是。
children

ToolbarBtnGroupProps

选项:

在原有属性基础上固定 type 属性,并继承了操作菜单的 ActionBasicProps 选项和按钮组的 BtnGroupOptions选项,同时添加了其他选项。

type
  • 类型:string
  • 属性值:btn-group
  • 必选:是。

ToolbarDividerProps

选项:

继承了工具栏的 ActionDividerProps 选项。

ToolbarSpaceProps

选项:

继承了工具栏的 ActionSpaceProps 选项。

type
  • 类型:string
  • 属性值:space
  • 必选:是。
space
  • 类型:number | [leading: number, trailing: number]
  • 必选:否。
flex
  • 类型:number | 'auto' | 'none'
  • 必选:否。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/tooltip/index.html b/3/lib/components/tooltip/index.html index da43628b59..985e5e8227 100644 --- a/3/lib/components/tooltip/index.html +++ b/3/lib/components/tooltip/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

提示消息

提示消息又称“工具提示”,在用户鼠标悬停在元素上时及时显示额外的内容。

使用方法

组件提供多种不同方向的展示方式,可以根据需求选择你要的效果。

html
<div class="flex justify-center gap-1">
@@ -81,7 +81,7 @@
 new zui.Tooltip('#tooltipShow6', {title: 'important 外观', type: 'important'});
 new zui.Tooltip('#tooltipShow7', {title: 'white 外观', type: 'white', className: 'text-darker border border-light'});
 </script>

选项

组件属性:

placement

提示信息的弹出方向。

  • 类型:'string';
  • 必选:否;
  • 可选项:'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'left-start' | 'left' | 'left-end' | 'right-start' | 'right' | 'right-end'
  • 默认:'top'

title

设定提示消息内容。

  • 类型:'string';
  • 必选:否。

trigger

设定提示消息触发方式。

  • 类型:'click' | 'hover';
  • 必选:否。

html

是否允许消息内容包含 HTML 格式源码。

  • 类型:boolean;
  • 必选:false

className

设定提示消息类名。

  • 类型:'string';
  • 必选:否。

type

设定提示消息外观类型。

  • 类型:'string';
  • 必选:否。

animation

决定是否应用淡入淡出动画。

  • 类型:boolean;
  • 必选:否;
  • 默认:true

arrow

控制提示消息组件的箭头的大小。

  • 类型:'number';
  • 必选:否;
  • 默认:5。

itemRender

指定一个回调函数用于对组件渲染进行自定义。

参数items 选项的单个配置;

返回值items 选项的单个配置。

beforeRender

指定一个回调函数在渲染之前调用,可重新配置组件选项。

参数:用户为按钮组组件件设置的 options

返回值:组件选项数据。

afterRender

指定一个回调函数在渲染之后调用。

参数:

  • firstRender:判断是否第一次渲染;
  • menu:组件信息。

beforeDestroy

指定一个回调函数在组件销毁之前调用,无参数。

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/tree/index.html b/3/lib/components/tree/index.html index 2d8eed46f9..1654f570d8 100644 --- a/3/lib/components/tree/index.html +++ b/3/lib/components/tree/index.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/components/upload-imgs/index.html b/3/lib/components/upload-imgs/index.html index 1d15c0488a..3dfc8f716b 100644 --- a/3/lib/components/upload-imgs/index.html +++ b/3/lib/components/upload-imgs/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

上传图片

用于表单上传图片。

使用方法

手动在 Html 元素上调用初始化函数并通过配置指定表单字段名即可使用上传文件组件。

html
<div id="example1"></div>
js
const upload = new UploadImgs('#example1', {
@@ -37,7 +37,7 @@
     tip: '可点击添加或拖拽上传,图片格式支持jpg、jpeg',
     accept: 'image/jpg, image/jpeg'
 });

选项

name

表单字段名。

  • 类型:string
  • 必选:是

showSize

是否显示文件大小。

  • 类型:boolean
  • 必选:否
  • 默认值:true

multiple

是否开启多文件上传。

  • 类型:boolean
  • 必选:否
  • 默认值:true

uploadText

上传按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'添加文件'

uploadIcon

上传按钮图标。

  • 类型:string
  • 必选:否

renameBtn

是否启用重命名按钮。

  • 类型:boolean
  • 必选:否
  • 默认值:true

renameIcon

重命名按钮图标。

  • 类型:string
  • 必选:否
  • 默认值:'edit'

renameText

重命名按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'重命名'

renameClass

重命名按钮类。

  • 类型:string
  • 必选:否

deleteBtn

是否启用删除按钮。

  • 类型:boolean
  • 必选:否
  • 默认值:true

deleteIcon

删除按钮图标。

  • 类型:string
  • 必选:否
  • 默认值:'trash'

deleteText

删除按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'删除'

deleteClass

删除按钮类。

  • 类型:string
  • 必选:否

tip

文件上传提示。

  • 类型:string
  • 必选:否

btnClass

上传按钮类。

  • 类型:string
  • 必选:否

onAdd

文件变更回调。

  • 类型:(files: File[] | File) => void
  • 必选:否

onDelete

删除文件回调。

  • 类型:(file: File) => void
  • 必选:否

onRename

重命名文件回调。

  • 类型:(newName: string, oldName: string) => void
  • 必选:否

onSizeChange

文件大小变更回调。

  • 类型:(size: number) => void
  • 必选:否

limitCount

上传文件最大数量限制。

  • 类型:number
  • 必选:否

accept

上传文件类型。

  • 类型:string
  • 必选:否

defaultFileList

默认文件列表。

  • 类型:File[]
  • 必选:否

limitSize

上传文件最大大小限制。

  • 类型:${number}${'B' | 'KB' | 'MB' | 'GB'} | false
  • 必选:否

duplicatedHint

重复文件提示。

  • 类型:string
  • 必选:否

exceededSizeHint

超出大小限制提示。

  • 类型:string
  • 必选:否

exceededCountHint

超过数量限制提示。

  • 类型:string
  • 必选:否

totalCountText

文件数量提示。

  • 类型:string
  • 必选:否
  • 默认值:'共 <span class="font-bold text-black">%s</span> 个文件 <span class="font-bold text-black">%s</span> 个文件等待上传。'

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/components/upload/index.html b/3/lib/components/upload/index.html index 9c631e7554..a79ab2797a 100644 --- a/3/lib/components/upload/index.html +++ b/3/lib/components/upload/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

上传文件

用于表单上传文件。

使用方法

手动在 Html 元素上调用初始化函数并通过配置指定表单字段名即可使用上传文件组件,默认已开启多文件上传、重命名和删除功能。

html
<div id="example1"></div>
js
const upload = new Upload('#example1', {
@@ -53,7 +53,7 @@
     name: 'files8',
     defaultFileList: [file1, file2]
 });

选项

name

表单字段名。

  • 类型:string
  • 必选:是

icon

文件图标。

  • 类型:string
  • 必选:否
  • 默认值:'file-o'

showIcon

是否显示文件图标。

  • 类型:boolean
  • 必选:否
  • 默认值:true

showSize

是否显示文件大小。

  • 类型:boolean
  • 必选:否
  • 默认值:true

multiple

是否开启多文件上传。

  • 类型:boolean
  • 必选:否
  • 默认值:true

listPosition

文件列表位置。

  • 类型:'bottom' | 'top'
  • 必选:否
  • 默认值:'bottom'

uploadText

上传按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'上传文件'

uploadIcon

上传按钮图标。

  • 类型:string
  • 必选:否

renameBtn

是否启用重命名按钮。

  • 类型:boolean
  • 必选:否
  • 默认值:true

renameIcon

重命名按钮图标。

  • 类型:string
  • 必选:否
  • 默认值:'edit'

renameText

重命名按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'重命名'

renameClass

重命名按钮类。

  • 类型:string
  • 必选:否

deleteBtn

是否启用删除按钮。

  • 类型:boolean
  • 必选:否
  • 默认值:true

deleteIcon

删除按钮图标。

  • 类型:string
  • 必选:否
  • 默认值:'trash'

deleteText

删除按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'删除'

deleteClass

删除按钮类。

  • 类型:string
  • 必选:否

confirmText

确认重命名按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'确定'

cancelText

取消重命名按钮文本。

  • 类型:string
  • 必选:否
  • 默认值:'取消'

useIconBtn

是否使用图标按钮。

  • 类型:boolean
  • 必选:否
  • 默认值:true

tip

文件上传提示。

  • 类型:string
  • 必选:否

btnClass

上传按钮类。

  • 类型:string
  • 必选:否

onAdd

文件变更回调。

  • 类型:(files: File[] | File) => void
  • 必选:否

onDelete

删除文件回调。

  • 类型:(file: File) => void
  • 必选:否

onRename

重命名文件回调。

  • 类型:(newName: string, oldName: string) => void
  • 必选:否

onSizeChange

文件大小变更回调。

  • 类型:(size: number) => void
  • 必选:否

draggable

是否启用拖拽功能。

  • 类型:boolean
  • 必选:否
  • 默认值:false

limitCount

上传文件最大数量限制。

  • 类型:number
  • 必选:否

accept

上传文件类型。

  • 类型:string
  • 必选:否

defaultFileList

默认文件列表。

  • 类型:File[]
  • 必选:否

limitSize

上传文件最大大小限制。

  • 类型:${number}${'B' | 'KB' | 'MB' | 'GB'} | false
  • 必选:否

duplicatedHint

重复文件提示。

  • 类型:string
  • 必选:否

exceededSizeHint

超出大小限制提示。

  • 类型:string
  • 必选:否

exceededCountHint

超过数量限制提示。

  • 类型:string
  • 必选:否

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/dtable/dtable/index.html b/3/lib/dtable/dtable/index.html index 46e92f0aaa..1dc07b3f25 100644 --- a/3/lib/dtable/dtable/index.html +++ b/3/lib/dtable/dtable/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

数据表格

数据表格是一种展示二维数据的强大方式,相比较普通的表格(<table>)组件,提供了更多的交互形式,并且拥有插件机制方便定制复杂交互的界面。

示例

基本功能

下面的示例中展示了数据表格的基本功能,包括:

  • 在固定区域内展示数据,超出部分可以滚动查看;
  • 滚动时固定两侧的列和表头;
  • 根据设定的列宽显示列;
  • 虚拟渲染(仅渲染用户能看到的单元格);
  • 根据列设置调整单元格对齐方式。

增强功能

下面的示例中展示了通过内置插件以及定制化选项实现的增强功能,包括:

  • 在表头显示排序标记;
  • 行选中交互;
  • 多层级数据结构,支持展开折叠;
  • 特殊交互和外观,包括:鼠标悬停效果、隔行变色、完整边框等;
  • 丰富的单元格渲染格式,包括链接、头像、环形进度条,格式化文本和操作按钮等。

使用

1. 引入

在你的代码中引入数据表格组件:

js
import {DTable} from 'zui/dtable';

2. 定义表格的列

通过一个对象数组依次序定义数据表格中的所有列,每个对象定义一个列,通过对象上的 name 属性来区分不同的列。例如:

js
const cols = [
@@ -357,7 +357,7 @@
 
   render(): void;
 }

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/dtable/dtable/plugins.html b/3/lib/dtable/dtable/plugins.html index 21e9716e8f..585523b5a7 100644 --- a/3/lib/dtable/dtable/plugins.html +++ b/3/lib/dtable/dtable/plugins.html @@ -13,8 +13,8 @@ - - + +
Skip to content

数据表格插件

富格式插件 rich

内置插件

让单元格支持展示丰富格式内容,包括链接、格式化字符串、HTML、迷你进度条以及时间日期等。

链接

在列定义上通过 link 属性设置单元格内容作为链接显示,支持以下值:

  • string:使用模版字符串来生成链接;
  • {url: string} & JSX.HTMLAttributes<HTMLAnchorElement>:使用对象来生成链接,对象中的其他属性将作为链接的属性;
  • ((info: {row: RowInfo, col: ColInfo}) => string | false | ({url: string} & JSX.HTMLAttributes<HTMLAnchorElement>)):使用函数来动态生成链接,如果在函数内返回 false 则不生成链接。

下面为一个实际的例子:

js
const cols = [
@@ -747,7 +747,7 @@
     /* 表头分组名称。 */
     headerGroup?: string;
 }

拖放改变列宽 resize

WIP

上下文菜单 contextmenu

WIP

快捷键 hotkey

WIP

鼠标移动事件支持 mousemove

WIP

拖放选择 selectable

WIP

过滤 filter

WIP

拖放移动 moveable

WIP

数据网格 datagrid

WIP

编辑状态 draft

WIP

可编辑 editable

WIP

历史记录 history

WIP

自动滚动 autoscroll

WIP

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/forms/checkbox/index.html b/3/lib/forms/checkbox/index.html index f92201e482..93d5a89088 100644 --- a/3/lib/forms/checkbox/index.html +++ b/3/lib/forms/checkbox/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

单选框和复选框

复选框(checkbox)允许用户选择多个选项,不同于 <select>,这些选项是直接展示的。 为 <input type="checkbox"> 设置 disabled 属性来应用禁用样式, 如果为 .checkbox 添加 disabled 类,则整个复选框包括文字部分都会应用禁用样式。 将多个复选框堆叠形成一个复选框组。

使用方法

基本样式复选框

html
<div class="checkbox">
@@ -97,7 +97,7 @@
 <div class="radio-primary"><input type="radio" name="primaryRadioGroup1" checked="checked" disabled="disabled" id="primaryradio4"><label for="primaryradio4">禁用</label></div>

高级外观还可以不使用 <input> 元素,在此种情况下,为 .checkbox-primary 或 .radio-primary 添加 .checked 类标记为选中状态,用户无法通过点击来切换选中状态,但可以通过程序手动添加或移除 .checked 来更改选中状态。

html
<div class="checkbox-primary"><label>未选中</label></div>
  <div class="checkbox-primary checked"><label>选中</label></div>
html
<div class="radio-primary"><label>未选中</label></div>
   <div class="radio-primary checked"><label>选中</label></div>

开关

CSS 类

单选框和复选框提供了如下CSS类

类型作用
checkbox实体类复选框组件
radio实体类单选框组件
checkbox-inline实体类内联复选框组件
radio-inline实体类内联单选框组件
checkbox-primary实体类高级外观的复选框组件
radio-primary实体类高级外观的单选框组件
switch实体类开关组件
checked修饰类强制使用选中外观
focus修饰类强制使用激活外观

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/forms/form/index.html b/3/lib/forms/form/index.html index 1a0fcdf949..aec448b567 100644 --- a/3/lib/forms/form/index.html +++ b/3/lib/forms/form/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

表单

基本样式表单

使用组件类.form-group来获得表单外观,通常搭配<form>,<label>以及<input>等表单控件使用

html
<form>
@@ -129,7 +129,7 @@
   <option value="banana">香蕉</option>
   <option value="orange">橘子</option>
 </select>

CSS 类

表单提供了如下CSS类

类型作用
form-group实体类元素作为表单组件
form-control实体类元素作为表单控件组件
form-tip实体类元素作为表单控件的提示性文本
form-horizontal工具类为表单启用水平排列样式
required工具类为表单控件启用必填标记样式
has-error工具类为表单控件启用报错样式
has-warning工具类为表单控件启用警告样式
has-success工具类为表单控件启用成功样式

CSS 变量

变量名称变量含义
--form-label-width表单文本宽度
--form-horz-label-align水平布局下文本对齐方向
--form-control-radius表单控件圆角
--form-control-border-color表单控件边框颜色
--form-focus-color表单控件响应聚焦边框颜色
--form-placeholder-color表单控件提示文本文字颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/forms/input-control/index.html b/3/lib/forms/input-control/index.html index d6c40e30cb..2bae2d99f8 100644 --- a/3/lib/forms/input-control/index.html +++ b/3/lib/forms/input-control/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

输入框

通过鼠标或键盘输入内容,通常用在表单、对话框上面。

使用方法

使用 input-control 类来获得输入框的外观和交互体验。

用户名
html
<div class="input-control">
@@ -102,7 +102,7 @@
 <div class="input-control">
   <input type="text" class="form-control shadow" placeholder="请填写" />
 </div>

CSS 类

输入框提供了如下 CSS 类:

类型作用
input-control实体类元素作为输入框组件
prefix工具类输入框前缀元素样式
suffix工具类输入框后缀元素样式
size-sm工具类输入框使用小号尺寸
size-lg工具类输入框使用大号尺寸

CSS 变量

输入框提供了如下 CSS 变量,可进行全局修改。

CSS 变量名作用
--input-fix-width输入框前/后缀的默认宽度
--input-fix-width-sm输入框前/后缀的小号宽度
--input-fix-width-lg输入框前/后缀的大号宽度

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/forms/input-group/index.html b/3/lib/forms/input-group/index.html index 06c81fec8a..7e8fe0569a 100644 --- a/3/lib/forms/input-group/index.html +++ b/3/lib/forms/input-group/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

输入组

通过在文本输入框 <input> 前面、后面或是两边加上文字、图标或按钮,可以实现对表单控件的扩展。 依赖form表单中的input组件

使用方法

使用 .input-group 类来获得按钮的外观和交互体验

可以使用input-group-addon类和input输入框组合,通过调换顺序实现不同种输入组外观显示

html
<div class="input-group">
@@ -120,7 +120,7 @@
     </div>
   </div>
 </div>

CSS类

输入组提供了如下 CSS 类:

类型作用
input-group实体类元素作为输入组组件
input-group-addon实体类元素作为输入组内部额外元素
size-sm工具类输入组使用小号尺寸
size-lg工具类输入组使用大号尺寸

CSS 变量

变量名称变量含义
--input-group-addon-bg输入组附加部分背景颜色
--input-group-addon-color输入组附加部分文字颜色

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/helpers/core/cash.html b/3/lib/helpers/core/cash.html index 0f8b2a9ccd..5df1cbf9ee 100644 --- a/3/lib/helpers/core/cash.html +++ b/3/lib/helpers/core/cash.html @@ -13,12 +13,12 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/helpers/core/component.html b/3/lib/helpers/core/component.html index 12babba253..a076c0c664 100644 --- a/3/lib/helpers/core/component.html +++ b/3/lib/helpers/core/component.html @@ -13,8 +13,8 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/helpers/helpers/index.html b/3/lib/helpers/helpers/index.html index 4b63ee0a05..96bec44279 100644 --- a/3/lib/helpers/helpers/index.html +++ b/3/lib/helpers/helpers/index.html @@ -13,12 +13,12 @@ - - + +
- + \ No newline at end of file diff --git a/3/lib/helpers/store/index.html b/3/lib/helpers/store/index.html index 4c1a01f764..65d6cb1b7c 100644 --- a/3/lib/helpers/store/index.html +++ b/3/lib/helpers/store/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

本地存储

本地存储(Local storage)是在浏览器本地存储应用数据的好途径。相比较 cookie 拥有更大的存储空间(相同域下一般达到 5M 以上存储空间),使用更灵活,而且不会在每次提交中发送到服务器。几乎所有浏览器都支持本地存储,甚至包括 IE。

本地存储包括尺寸存储和会话存储,对应的是浏览器内置的 localStoragesessionStorage

此 JS 插件提供了一系列方法用于读写本地存储数据。相比较直接使用这些浏览器原生接口,Store 类在读写数据时会自动进行转换,所以你可以存储任何可以被系列化为 JSON 的数据,例如数值、数组和复杂对象,而不仅仅是字符串。

引入

js
import {store} from 'zui/store';

store 为默认的持久存储管理实例,可以直接使用上面的各种方法进行数据操作。如需使用会话存储数据,则只需要通过 store.session 访问会话存储类型的管理实例即可。

综合示例

(待定:提供一个例子读取示例数据,并提供操作按钮让用户手动添加数据进行存储)

存储数据

存储数据使用 Store 实例上的 set 方法。

示例

js
store.set('mySecretCode', 1314520);

读取数据

读取数据使用 Store 实例上的 get 方法。

示例

js
store.get('mySecretCode'); // 基于存储数据的例子应该返回 1314520

移除数据

读取数据使用 Store 实例上的 remove 方法。

示例

js
store.remove('mySecretCode');

遍历数据

遍历数据使用 Store 实例上的 each 方法。

示例

js
store.each((name, value) => {
@@ -38,7 +38,7 @@
 store.get('mySecretCode');          // 返回 1
 myStore.get('mySecretCode');        // 返回 2
 mySessionStore.get('mySecretCode'); // 返回 3

API

C Store

Store 类。

属性

名称类型定义
typeStoreType存储类型
sessionStore与当前存储同名的会话存储实例

方法

方法名定义
get获取数据
set存储数据
remove移除数据
each遍历数据
getAll获取所有数据

F Store.set(key, value)

存储数据。

定义

ts
set(key: string, value: any) => void;

参数

参数类型定义
keystring存储的数据名称
valueany要存储的数据

方法

F Store.get(key, defaultValue)

读取数据。

定义

ts
get(key: string, defaultValue?: any) => any;

参数

参数类型定义
keystring读取的数据名称
defaultValueany当没有读取数据时返回此默认值

返回值

类型定义
any读取到的数据

F Store.remove(key)

移除数据

定义

ts
remove(key: string) => void;

参数

参数类型定义
keystring要移除的数据名称

F Store.each(callback)

遍历数据。

定义

ts
each(callback: (name: string, value: any) => void) => void;

参数

参数类型定义
callbackfunction遍历回调函数

其中 callback 参数:

参数类型定义
namestring本次遍历存储的名称
valueany本次遍历存储的值

F Store.getAll()

获取所有存储的数据。

定义

ts
getAll() => Record<string, any>;

返回值

类型定义
Record<string, any>通过一个对象返回所有存储的数据,对象的属性名和值分别对应存储的名称和值

T StoreType

本地存储类型。

定义

ts
type StoreType = 'local' | 'session';

常量定义

定义
'local'本地持久存储
'session'本地会话存储

V store

默认的 store 实例,并包含用于创建新的 Store 实例的快捷方法。

定义

ts
var store: Store & {create: StoreCreateFunc}

其中 create 成员为创建 Store 实例的快捷方法。

F StoreCreateFunc

Store 实例创建方法。

定义

ts
type StoreCreateFunc = (name?: string, type: StoreType = 'local') => Store;

参数

参数类型定义
namestring本地存储实例名称
typeStoreType存储类型,默认为 'local'

MIT License (MIT)

- + \ No newline at end of file diff --git a/3/lib/icons/icons/index.html b/3/lib/icons/icons/index.html index 6d2b2e9694..180e8c0409 100644 --- a/3/lib/icons/icons/index.html +++ b/3/lib/icons/icons/index.html @@ -13,8 +13,8 @@ - - + +
Skip to content

图标

所有图标

    使用方法

    html
    <i class="icon icon-resize"></i>

    尺寸

    使用 icon-*x 类实现不同大小的图标,支持五种图标大小

    html
    <i class="icon icon-5x icon-resize"></i>
    @@ -30,7 +30,7 @@
       <i class="icon icon-star ping"></i>
       <i class="icon icon-star pulse"></i>
       <i class="icon icon-star bounce"></i>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/lib/index.html b/3/lib/index.html index 9538bdd22d..83495dba68 100644 --- a/3/lib/index.html +++ b/3/lib/index.html @@ -13,12 +13,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/public/icons/fontawesome-license.html b/3/public/icons/fontawesome-license.html index 18b2cf0e1a..10e82a1fd6 100644 --- a/3/public/icons/fontawesome-license.html +++ b/3/public/icons/fontawesome-license.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    License

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/themes/index.html b/3/themes/index.html index 9da7faa335..3865ecf743 100644 --- a/3/themes/index.html +++ b/3/themes/index.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/backgrounds/utilities/index.html b/3/utilities/backgrounds/utilities/index.html index 88281cef42..dbfa9c613a 100644 --- a/3/utilities/backgrounds/utilities/index.html +++ b/3/utilities/backgrounds/utilities/index.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    背景色

    使用bg-*给元素添加背景色

    效果展示

    语义化配色

    bg-primary
    #2B80FF
    bg-secondary
    #37B2FE
    bg-success
    #17CE97
    bg-warning
    #FFA34D
    bg-danger
    #FF5858
    bg-important
    #FF4F9E
    bg-special
    #9D5EFF

    黑白配色

    bg-white
    #FFFFFF
    bg-lighter
    #F5F5F5
    bg-light
    #E3E4E9
    bg-gray
    #9EA3B0
    bg-darken
    #5E626D
    bg-darker
    #1B1F28
    bg-black
    #000000

    特殊配色

    bg-surface
    #F5F5F5
    bg-inverse
    #3C4353
    bg-transparent
    bg-inherit

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/borders/utilities/border-color.html b/3/utilities/borders/utilities/border-color.html index efd72464f8..d73f72aedb 100644 --- a/3/utilities/borders/utilities/border-color.html +++ b/3/utilities/borders/utilities/border-color.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    边框颜色

    使用'border-*' 设置元素边框颜色。

    效果展示

    语义化配色

    border-primary
    #2B80FF
    border-secondary
    #37B2FE
    border-success
    #17CE97
    border-warning
    #FFA34D
    border-danger
    #FF5858
    border-important
    #FF4F9E
    border-special
    #9D5EFF

    黑白配色

    border-white
    #FFFFFF
    border-lighter
    #F5F5F5
    border-light
    #E3E4E9
    border-gray
    #9EA3B0
    border-dark
    #5E626D
    border-darker
    #1B1F28
    border-black
    #000000

    特殊配色

    border-surface
    #F5F5F5
    border-inverse
    #3C4353
    border-transparent
    border-inherit
    border-current

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/borders/utilities/border-radius.html b/3/utilities/borders/utilities/border-radius.html index c75c92cb8f..69443ef691 100644 --- a/3/utilities/borders/utilities/border-radius.html +++ b/3/utilities/borders/utilities/border-radius.html @@ -13,12 +13,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/borders/utilities/border-width.html b/3/utilities/borders/utilities/border-width.html index adf909e4aa..4d4af14bbc 100644 --- a/3/utilities/borders/utilities/border-width.html +++ b/3/utilities/borders/utilities/border-width.html @@ -13,15 +13,15 @@ - - + +
    Skip to content

    边框大小

    使用'border-*' 设置元素边框圆角大小。

    效果展示

    无边框

    border-0

    边框宽度

    border
    border-2
    border-4

    单边有边框

    border-l
    border-t
    border-b-2
    border-r-4

    单边无边框

    border-l-0
    border-t-0
    border-b-0
    border-r-0
    html
    <div class="broder border-l-0 -h-8 border-primary"></div>
     <div class="broder border-t-0 -h-8 border-primary"></div>
     <div class="broder border-b-0 -h-8 border-primary"></div>
     <div class="broder border-r-0 -h-8 border-primary"></div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/animation.html b/3/utilities/effects/utilities/animation.html index 3713a286a3..50bea67aa5 100644 --- a/3/utilities/effects/utilities/animation.html +++ b/3/utilities/effects/utilities/animation.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    动画

    效果展示

    旋转

    使用spin给元素添加旋转动画

    html
    <button type="button" class="btn primary">
    @@ -32,7 +32,7 @@
     </div>

    弹跳

    使用bounce给元素添加弹跳动画

    html
    <button type="button" class="btn primary">
       <i class="bounce icon icon-arrow-down text-white"></i> 弹跳
     </button>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/filter.html b/3/utilities/effects/utilities/filter.html index acd4f213f6..6d29e44b38 100644 --- a/3/utilities/effects/utilities/filter.html +++ b/3/utilities/effects/utilities/filter.html @@ -14,8 +14,8 @@ - - + +
    Skip to content

    Filter函数

    效果展示

    高斯模糊

    通过blur-*给图片添加高斯模糊样式。

    原始
    blur-none
    blur-sm
    blur
    blur-md
    blur-lg
    blur-xl

    灰度和反色

    通过grascale将图像转为灰度图像;通过invert将图像设置为反色。

    原始
    grayscale
    invert

    图像阴影

    通过dsd-*给图像设置阴影效果。

    原始
    dsd-none
    dsd-sm
    dsd
    dsd-md
    dsd-lg
    dsd-xl
    dsd-2xl
    html
    <img class="dsd-sm" ... >

    覆盖区域模糊

    通过bg-blur-*添加覆盖区域模糊样式。

    ZUI3
    原始
    ZUI3
    bg-blur-none
    ZUI3
    bg-blur-sm
    ZUI3
    bg-blur
    ZUI3
    bg-blur-md
    ZUI3
    bg-blur-lg
    ZUI3
    bg-blur-xl
    ZUI3
    bg-blur-2xl
    ZUI3
    bg-blur-3xl
    html
    <div class="relative w-24 h-16">
    @@ -24,7 +24,7 @@
           ZUI3
         </div>
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/flip.html b/3/utilities/effects/utilities/flip.html index 83eb1e7cfb..e1bbd1ad71 100644 --- a/3/utilities/effects/utilities/flip.html +++ b/3/utilities/effects/utilities/flip.html @@ -13,12 +13,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/opacity.html b/3/utilities/effects/utilities/opacity.html index 778c7f1cf3..59093825b6 100644 --- a/3/utilities/effects/utilities/opacity.html +++ b/3/utilities/effects/utilities/opacity.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    不透明度

    使用opacity-*设置元素的不透明度

    opacity-0
    opacity-5
    opacity-10
    opacity-20
    opacity-25
    opacity-30
    opacity-40
    opacity-50
    opacity-60
    opacity-70
    opacity-75
    opacity-80
    opacity-90
    opacity-95
    opacity-100

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/rotate.html b/3/utilities/effects/utilities/rotate.html index d1804da392..59af983ed8 100644 --- a/3/utilities/effects/utilities/rotate.html +++ b/3/utilities/effects/utilities/rotate.html @@ -14,12 +14,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/scale.html b/3/utilities/effects/utilities/scale.html index 4fdc602363..175c6816e3 100644 --- a/3/utilities/effects/utilities/scale.html +++ b/3/utilities/effects/utilities/scale.html @@ -14,12 +14,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/effects/utilities/shadow.html b/3/utilities/effects/utilities/shadow.html index b722c17afa..ba93825a9a 100644 --- a/3/utilities/effects/utilities/shadow.html +++ b/3/utilities/effects/utilities/shadow.html @@ -13,12 +13,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/align-content.html b/3/utilities/flex/utilities/align-content.html index 43cd8f33e3..1ed0b191f0 100644 --- a/3/utilities/flex/utilities/align-content.html +++ b/3/utilities/flex/utilities/align-content.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    align-content

    使用content-*应用CSSalign-content属性设置Flex容器中多行子元素沿交叉轴的对齐方式。

    效果展示

    content-center

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    content-start

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    content-end

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    content-between

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    content-around

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    content-evenly

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/align-items.html b/3/utilities/flex/utilities/align-items.html index ffb79e160d..353df8d7ae 100644 --- a/3/utilities/flex/utilities/align-items.html +++ b/3/utilities/flex/utilities/align-items.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    align-items

    使用items-*应用CSSalign-items属性 属性设置 Flex 容器中的交叉轴方向上的对齐方式。

    items-center

    1
    2
    3
    4
    5

    items-start

    1
    2
    3
    4
    5

    items-end

    1
    2
    3
    4
    5

    items-baseline

    1
    2
    3
    4
    5

    items-stretch

    1
    2
    3
    4
    5

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/align-self.html b/3/utilities/flex/utilities/align-self.html index a2f928c3d1..141e8ad9ed 100644 --- a/3/utilities/flex/utilities/align-self.html +++ b/3/utilities/flex/utilities/align-self.html @@ -13,15 +13,15 @@ - - + +
    Skip to content

    align-self

    使用 self-* 应用 CSS align-self 属性设置当前元素在 Grid 或 Flex 容器中的交叉轴方向上的对齐方式。

    self-auto

    self-auto
    default
    default
    default
    default

    self-start

    self-start
    default
    default
    default
    default

    self-end

    self-end
    default
    default
    default
    default

    self-center

    self-center
    default
    default
    default
    default

    self-stretch

    self-stretch
    default
    default
    default
    default

    self-baseline

    self-baseline
    default
    default
    default
    default
    html
    <div class="flex flex-wrap ...">
         <div class="align-auto ...">
         ...
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/basis.html b/3/utilities/flex/utilities/basis.html index e766a31cb9..aec8cc42b4 100644 --- a/3/utilities/flex/utilities/basis.html +++ b/3/utilities/flex/utilities/basis.html @@ -13,15 +13,15 @@ - - + +
    Skip to content

    basis

    使用 basis-* 应用 CSS flex-basis 属性设置当前元素在 Grid 或 Flex 容器中弹性盒伸缩的基准值。

    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    14
    16
    20
    24
    28
    32
    36
    40
    44
    48
    52
    56
    60
    64
    72
    80
    96
    full
    auto
    px
    html
    <div class="flex flex-wrap ...">
         <div class="basis-* ..."></div>
         ...
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/direction.html b/3/utilities/flex/utilities/direction.html index 1a12b66d3e..1a64911079 100644 --- a/3/utilities/flex/utilities/direction.html +++ b/3/utilities/flex/utilities/direction.html @@ -13,14 +13,14 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/flex.html b/3/utilities/flex/utilities/flex.html index 24a99cf7f1..8d7e6ed7ff 100644 --- a/3/utilities/flex/utilities/flex.html +++ b/3/utilities/flex/utilities/flex.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    flex

    使用flex-*应用CSSflex属性设置当前元素在Grid或Flex容器中的伸缩方式。

    flex-1

    24 * 16
    24 * 16
    24 * 16

    flex-initial

    24 * 16
    24 * 16
    24 * 16

    flex-none

    24 * 16
    24 * 16
    24 * 16
    html
    <div class="flex ...">
    @@ -22,7 +22,7 @@
         <div class="flex-1 ..."></div>
         <div class="flex-1 ..."></div>
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/gap.html b/3/utilities/flex/utilities/gap.html index ee8ece1c1b..288ae5f3da 100644 --- a/3/utilities/flex/utilities/gap.html +++ b/3/utilities/flex/utilities/gap.html @@ -13,13 +13,13 @@ - - + +
    Skip to content

    gap

    使用gap-*应用CSS属性gap设置Flex容器中元素间距。

    gap-0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-4

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-5

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-5

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-5

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-6

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-6

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-6

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-7

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-7

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-7

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-8

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-x-8

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    gap-y-8

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    html
    <div class="flex flex-wrap gap-* ...">
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/grow.html b/3/utilities/flex/utilities/grow.html index 4b7e922b4b..0d3196023f 100644 --- a/3/utilities/flex/utilities/grow.html +++ b/3/utilities/flex/utilities/grow.html @@ -13,13 +13,13 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/justify-content.html b/3/utilities/flex/utilities/justify-content.html index 180014faea..ca90d07818 100644 --- a/3/utilities/flex/utilities/justify-content.html +++ b/3/utilities/flex/utilities/justify-content.html @@ -13,15 +13,15 @@ - - + +
    Skip to content

    justify-content

    使用justify-*应用CSSjustify-content属性设置Flex容器中元素沿水平轴的对齐方式。

    justify-start

    1
    2
    3
    4

    justify-end

    1
    2
    3
    4

    justify-center

    1
    2
    3
    4

    justify-between

    1
    2
    3
    4

    justify-around

    1
    2
    3
    4

    justify-evenly

    1
    2
    3
    4
    html
    <div class="justify-start flex flex-wrap ...">
         <div></div>
         ...
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/order.html b/3/utilities/flex/utilities/order.html index 19aff4400e..68ec51f622 100644 --- a/3/utilities/flex/utilities/order.html +++ b/3/utilities/flex/utilities/order.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    order

    使用order-*应用CSS属性order设置当前元素在Flex容器中的排列顺序

    1
    order-12
    2
    order-11
    3
    order-10
    4
    order-9
    5
    order-8
    6
    order-7
    7
    order-6
    8
    order-5
    9
    order-4
    10
    order-3
    11
    order-2
    12
    order-1
    html
    <div class="flex flex-wrap gap-3 ...">
    @@ -28,7 +28,7 @@
       <div class="order-first ...">2</div>
       <div class="order-none ...">3</div>
     <div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/shrink.html b/3/utilities/flex/utilities/shrink.html index 84e426739a..0736df1524 100644 --- a/3/utilities/flex/utilities/shrink.html +++ b/3/utilities/flex/utilities/shrink.html @@ -13,15 +13,15 @@ - - + +
    Skip to content

    shrink

    使用shrink应用CSSflex-shrinl属性设置Flex容器中元素是否缩小。

    shrink
    shrink-0
    html
    <div class="w-64 flex gap-3">
         <div class="w-48 h-16 shrink"></div>
         <div class="w-48 h-16 shrink-0"></div>
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/flex/utilities/wrap.html b/3/utilities/flex/utilities/wrap.html index 726d1a7be1..debfaa1135 100644 --- a/3/utilities/flex/utilities/wrap.html +++ b/3/utilities/flex/utilities/wrap.html @@ -13,14 +13,14 @@ - - + +
    Skip to content

    wrap

    添加flex-*应用CSSflex-wrap相关属性设置Flex容器中换行方式

    flex-wrap

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    flex-wrap-reverse

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    flex-nowrap

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    html
    <div class="flex flex-wrap ...">
         ...
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/index.html b/3/utilities/index.html index 6e42c2aaa7..0d75edfb3d 100644 --- a/3/utilities/index.html +++ b/3/utilities/index.html @@ -13,12 +13,12 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/interactivity/utilities/disabled.html b/3/utilities/interactivity/utilities/disabled.html index 2486fb881d..494bb2d666 100644 --- a/3/utilities/interactivity/utilities/disabled.html +++ b/3/utilities/interactivity/utilities/disabled.html @@ -13,13 +13,13 @@ - - + +
    - + \ No newline at end of file diff --git a/3/utilities/interactivity/utilities/pointer-events.html b/3/utilities/interactivity/utilities/pointer-events.html index 3dc9a43906..ac6072c2a0 100644 --- a/3/utilities/interactivity/utilities/pointer-events.html +++ b/3/utilities/interactivity/utilities/pointer-events.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    指向事件

    用于控制元素是否响应指向事件的工具类。

    工具类属性
    events-nonepointer-events: none;
    events-autopointer-events: auto;

    效果展示

    隐蔽事件

    使用 events-none 使元素忽略指向事件。指向事件仍然会在子元素上触发,并传递到目标元素的下方。

    html
    <button class="btn events-none">隐蔽事件</button>

    开启事件

    使用 events-auto 来恢复浏览器对指向事件(如 :hoverclick )的默认行为。

    html
    <button class="btn events-auto">开启事件</button>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/interactivity/utilities/scroll.html b/3/utilities/interactivity/utilities/scroll.html index 4dc83bb949..d26a12872c 100644 --- a/3/utilities/interactivity/utilities/scroll.html +++ b/3/utilities/interactivity/utilities/scroll.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    滚动

    用于指定滚动框滚动行为的工具类。

    工具类属性
    scroll-autoscroll-behavior:auto;
    scroll-smoothscroll-behavior:smooth

    效果展示

    立即滚动

    使用 scroll-auto 使得滚动条立即滚动。点击按钮查看滚动效果:

    1
    2
    3
    4
    html
    <div class="scroll-auto">
    @@ -40,7 +40,7 @@
       <label for="smoothThree">3</label>
       <label for="smoothFour">4</label>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/interactivity/utilities/state.html b/3/utilities/interactivity/utilities/state.html index fc77ed861c..355712669b 100644 --- a/3/utilities/interactivity/utilities/state.html +++ b/3/utilities/interactivity/utilities/state.html @@ -13,13 +13,13 @@ - - + +
    Skip to content

    状态

    用于为元素设置类似于按钮或链接状态的工具类。

    工具类属性
    statecursor: pointer; position: relative;

    效果展示

    未使用 state 类
    使用 state 类
    html
    <div class="...">未使用 state 类</div>
     <div class="state ...">使用 state 类</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/interactivity/utilities/user-select.html b/3/utilities/interactivity/utilities/user-select.html index 1072f2bd43..923da6f4d5 100644 --- a/3/utilities/interactivity/utilities/user-select.html +++ b/3/utilities/interactivity/utilities/user-select.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    用户选择

    用于控制用户能否选中文本的工具类。

    工具类属性
    select-noneuser-select: none;
    select-textuser-select: text;
    select-alluser-select: all;
    select-autouser-select: auto;

    效果展示

    禁用文本选择

    使用工具类 select-none 来防止选择元素及其子元素中的文本。

    此文本不可选择
    html
    <div class="select-none ...">此文本不可选择</div>

    允许选择文本

    使用工具类 select-text 允许选择元素及其子元素中的文本。

    此文本可选择
    html
    <div class="select-text ...">此文本可选择</div>

    一键选择所有文本

    使用工具类 select-all 在用户点击时自动选择元素中的所有文本。

    单击此文本中的任意位置以全选
    html
    <div class="select-all ...">单击此文本中的任意位置以全选</div>

    自动

    使用工具类 select-auto 来使用默认的浏览器行为来选择文本。对于撤销其他工具类(如 .select-none)在不同断点的行为时很有用。

    此文本可选择
    html
    <div class="select-auto ...">此文本可选择</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/aspect-ratio.html b/3/utilities/layout/utilities/aspect-ratio.html index e9c1b69040..bbf16f0bfa 100644 --- a/3/utilities/layout/utilities/aspect-ratio.html +++ b/3/utilities/layout/utilities/aspect-ratio.html @@ -13,14 +13,14 @@ - - + +
    Skip to content

    宽高比

    为元素提供固定的宽高比,详细配置可参考 Tailwind 官网

    工具类属性
    aspect-autoaspect-ratio: auto;
    aspect-squareaspect-ratio: 1 / 1;
    aspect-videoaspect-ratio: 16 / 9;

    效果展示

    html
    <div class="w-16 h-2 aspect-auto"></div>
     <div class="w-16 aspect-square"></div>
     <div class="w-16 aspect-video"></div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/container.html b/3/utilities/layout/utilities/container.html index a986d559b1..b25a81d591 100644 --- a/3/utilities/layout/utilities/container.html +++ b/3/utilities/layout/utilities/container.html @@ -13,14 +13,14 @@ - - + +
    Skip to content

    容器

    container 类设置一个元素的 max-width 来匹配当前断点的 min-width。如果您想为一组固定的屏幕尺寸设计,而不是试图适应一个完全流动的视窗,这很有用。

    工具类断点属性
    containerwidth: 100%;
    containersm (640px)max-width: 640px;
    containersm (768px)max-width: 768px;
    containersm (1024px)max-width: 1024px;
    containersm (1280px)max-width: 1280px;
    containersm (1536px)max-width: 1536px;

    使用方法

    html
    <div class="container">
       <!-- ... -->
     </div>

    提示

    请注意,容器不会自动居中,也没有任何内置的水平方向的内边距。

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/display.html b/3/utilities/layout/utilities/display.html index 523fcff524..d90e22bd99 100644 --- a/3/utilities/layout/utilities/display.html +++ b/3/utilities/layout/utilities/display.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    显示类型

    控制元素显示类型的工具类。

    工具类属性
    blockdisplay: block;
    inline-blockdisplay: inline-block;
    inlinedisplay: inline;
    flexdisplay: flex;
    inline-flexdisplay: inline-flex;
    tabledisplay: table;
    table-celldisplay: table-cell;
    table-rowdisplay: table-row;
    list-itemdisplay: list-item;
    hiddendisplay: hidden;

    效果展示

    块级元素

    使用工具类 block 创建一个块级元素。

    span 元素span 元素
    html
    <span>span 元素</span>
    @@ -47,7 +47,7 @@
       <div class="...">2</div>
       <div class="...">3</div>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/floats.html b/3/utilities/layout/utilities/floats.html index 21d9c9deaf..6e53e630fe 100644 --- a/3/utilities/layout/utilities/floats.html +++ b/3/utilities/layout/utilities/floats.html @@ -14,8 +14,8 @@ - - + +
    Skip to content

    浮动

    用于设置元素浮动或清除浮动影响的工具类。

    工具类属性
    pull-rightfloat: right;
    pull-leftfloat: left;
    clearfix.clearfix::after {content: ""; display: block; clear: both;}

    提示

    浮动应当仅适用于实现文字环绕效果,布局请使用 flex 等工具类。

    效果展示

    向右浮动

    使用工具类 pull-right 将一个元素浮动到其容器的右边。

    ZUI3 是一个开箱即用的组合式前端 UI 框架。ZUI3 组件库内置了大量组件,并支持集中开发、调试和打包,其中打包还支持只选择指定的组件进行个性化定制,同步输出组件库文档。但当需求扩展到组件库之外时,就需要用到扩展组件库了。ZUI3 支持扩展组件库模式,可以从其他位置引入一个或多个组件库目录,享受集中开发、调试和打包。下面介绍扩展组件库的使用方法。ZUI3 每个组件在一个独立的目录内,拥有自己的 package.json 文件,使得组件可以独立作为 npm 包来使用,也可以单独作为子项目进行开发维护。通常组件通过在 package.json 文件中设置属性 private: true 来让包仅在 zui3 工作空间内可用,但组件仍然拥有作为公开的包发布到 npm 上进行独立使用。

    html
    <div class="clearfix">
    @@ -25,7 +25,7 @@
       <img class="pull-left mr-4 h-24" src="/favicon.svg">
       <p>ZUI3 是一个开箱即用的组合式前端 UI 框架。ZUI3 组件库内置了大量组件,并支持集中开发、调试和打包,其中打包还支持只选择指定的组件进行个性化定制,同步输出组件库文档。但当需求扩展到组件库之外时,就需要用到扩展组件库了。ZUI3 支持扩展组件库模式,可以从其他位置引入一个或多个组件库目录,享受集中开发、调试和打包。下面介绍扩展组件库的使用方法。ZUI3 每个组件在一个独立的目录内,拥有自己的 package.json 文件,使得组件可以独立作为 npm 包来使用,也可以单独作为子项目进行开发维护。通常组件通过在 package.json 文件中设置属性 private: true 来让包仅在 zui3 工作空间内可用,但组件仍然拥有作为公开的包发布到 npm 上进行独立使用。</p>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/object-fit.html b/3/utilities/layout/utilities/object-fit.html index c6a2df89ca..c4895cd8da 100644 --- a/3/utilities/layout/utilities/object-fit.html +++ b/3/utilities/layout/utilities/object-fit.html @@ -14,8 +14,8 @@ - - + +
    Skip to content

    内容适配

    元素的内容应该如何去适应指定容器的高度与宽度。

    工具类属性
    object-containobject-fit: contain;
    object-coverobject-fit: cover;
    object-fillobject-fit: fill;
    object-noneobject-fit: none;
    object-scale-downobject-fit: scale-down;

    效果展示

    包含

    使用工具类 object-contain 调整元素内容的大小,使其保持在容器内。

    html
    <div class="bg-surface">
    @@ -29,7 +29,7 @@
     </div>

    缩小

    以原始大小显示元素的内容,但必要时使用 object-scale-down 将其缩小以适应其容器。

    html
    <div class="bg-surface">
       <img src="/favicon.svg" class="object-scale-down h-48 w-full">
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/overflow.html b/3/utilities/layout/utilities/overflow.html index 1912b58151..e0b8922bd2 100644 --- a/3/utilities/layout/utilities/overflow.html +++ b/3/utilities/layout/utilities/overflow.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    溢出

    用于控制元素如何处理超出容器的内容的工具类。

    工具类属性
    overflow-autooverflow: auto;
    overflow-hiddenoverflow: hidden;
    overflow-cliptext-overflow: clip;
    overflow-visibleoverflow: visible;
    overflow-scrolloverflow: scroll;
    overflow-x-autooverflow-x: auto;
    overflow-y-autooverflow-y: auto;
    overflow-x-hiddenoverflow-x: hidden;
    overflow-y-hiddenoverflow-y: hidden;
    overflow-x-visibleoverflow-x: visible;
    overflow-y-visibleoverflow-y: visible;
    overflow-x-scrolloverflow-x: scroll;
    overflow-y-scrolloverflow-y: scroll;

    效果展示

    自动

    使用工具类 overflow-auto 在一个元素的内容溢出该元素的边界时为其添加滚动条。不像 overflow-scroll 总是显示滚动条,这个工具类只在需要滚动时才会显示。

    虞美人·春花秋月何时了

    五代·李煜

    春花秋月何时了?往事知多少。
    小楼昨夜又东风,故国不堪回首月明中。
    雕栏玉砌应犹在,只是朱颜改。
    问君能有几多愁?恰似一江春水向东流

    html
    <div class="overflow-auto h-24">
    @@ -74,7 +74,7 @@
       <p><small>五代·李煜</small></p>
       <p>春花秋月何时了?往事知多少。小楼昨夜又东风,故国不堪回首月明中。雕栏玉砌应犹在,只是朱颜改。问君能有几多愁?恰似一江春水向东流</p>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/position.html b/3/utilities/layout/utilities/position.html index 4e18de29c0..12c5c3181c 100644 --- a/3/utilities/layout/utilities/position.html +++ b/3/utilities/layout/utilities/position.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    定位

    用于控制元素在DOM中的位置的工具类。

    工具类属性
    staticposition: static;
    fixedposition: fixed;
    absoluteposition: absolute;
    relativeposition: relative;
    stickyposition: sticky;

    使用方法

    staticabsolute

    使用 static 根据常规的文档流来定位元素,浏览器默认 position 取值就是 static。任何偏移都将被忽略,而且该元素不会作为绝对定位的子元素的位置参考。

    Static 父元素

    Absolute 子元素

    html
    <div class="static h-20 ...">
    @@ -41,7 +41,7 @@
         <!-- ... -->
       </div>
     </div>

    fixed

    使用 fixed 来定位一个元素相对于浏览器窗视口的位置。偏移量是相对于视口计算的,且该元素将作为绝对定位的子元素的位置参考。

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/top-right-bottom-left.html b/3/utilities/layout/utilities/top-right-bottom-left.html index d718eb775f..625a51a766 100644 --- a/3/utilities/layout/utilities/top-right-bottom-left.html +++ b/3/utilities/layout/utilities/top-right-bottom-left.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    上/右/下/左

    用于控制定位元素的位置的工具类。

    工具类属性
    inset-0top: 0px; right: 0px; bottom: 0px; left: 0px;
    inset-autotop: auto; right: auto; bottom: auto; left: auto;
    inset-x-0left: 0px; right: 0px;
    inset-y-0top: 0px; bottom: 0px;
    top-0top: 0px;
    right-0right: 0px;
    bottom-0bottom: 0px;
    left-0left: 0px;
    top-fulltop: 100%;
    right-fullright: 100%;
    bottom-fullbottom: 100%;
    left-fullleft: 100%;
    top-autotop: auto;
    right-autoright: auto;
    bottom-autobottom: auto;
    left-autoleft: auto;

    效果展示

    1
    2
    3
    4
    html
    <div class="relative ...">
    @@ -40,7 +40,7 @@
     <div class="relative ...">
       <div class="absolute right-0 bottom-0 ...">8</div>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/visibility.html b/3/utilities/layout/utilities/visibility.html index 607ac8b4b0..6933f4db8f 100644 --- a/3/utilities/layout/utilities/visibility.html +++ b/3/utilities/layout/utilities/visibility.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    可见性

    用于控制元素可见性的工具类。

    工具类属性
    visiblevisibility: visible;
    invisiblevisibility: hidden;

    效果展示

    可见
    1
    2
    不可见
    1
    html
    <div>可见</div>
    @@ -28,7 +28,7 @@
       <div class="...">1</div>
       <div class="invisible ...">2</div>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/layout/utilities/z-index.html b/3/utilities/layout/utilities/z-index.html index ed5d9bfb5f..345791bdaa 100644 --- a/3/utilities/layout/utilities/z-index.html +++ b/3/utilities/layout/utilities/z-index.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    层级

    用于控制元素的堆栈顺序的工具类。

    工具类属性
    z-0z-index: 0;
    z-10z-index: 10;
    z-20z-index: 20;
    z-30z-index: 30;
    z-40z-index: 40;
    z-50z-index: 50;
    z-autoz-index: auto;

    效果展示

    z-50
    z-40
    z-30
    z-20
    z-10
    html
    <div class="z-50 ...">z-50</div>
    @@ -22,7 +22,7 @@
     <div class="z-30 ...">z-30</div>
     <div class="z-20 ...">z-20</div>
     <div class="z-10 ...">z-10</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/sizing/utilities/height.html b/3/utilities/sizing/utilities/height.html index 43b1caf366..e57571a98a 100644 --- a/3/utilities/sizing/utilities/height.html +++ b/3/utilities/sizing/utilities/height.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    详细配置可参考 Tailwind 官网

    工具类属性
    .h-0height: 0px;
    .h-pxheight: 1px;
    .h-0.5height: 0.125rem; /* 2px */
    .h-1height: 0.25rem; /* 4px */
    .h-1.5height: 0.375rem; /* 6px */
    .h-2height: 0.5rem; /* 8px */
    .h-2.5height: 0.625rem; /* 10px */
    .h-3height: 0.75rem; /* 12px */
    .h-3.5height: 0.875rem; /* 14px */
    .h-4height: 1rem; /* 16px */
    .h-5height: 1.25rem; /* 20px */
    .h-6height: 1.5rem; /* 24px */
    .h-7height: 1.75rem; /* 28px */
    .h-8height: 2rem; /* 32px */
    .h-9height: 2.25rem; /* 36px */
    .h-10height: 2.5rem; /* 40px */
    .h-11height: 2.75rem; /* 44px */
    .h-12height: 3rem; /* 48px */
    .h-14height: 3.5rem; /* 56px */
    .h-16height: 4rem; /* 64px */
    .h-20height: 5rem; /* 80px */
    .h-24height: 6rem; /* 96px */
    .h-28height: 7rem; /* 112px */
    .h-32height: 8rem; /* 128px */
    .h-36height: 9rem; /* 144px */
    .h-40height: 10rem; /* 160px */
    .h-44height: 11rem; /* 176px */
    .h-48height: 12rem; /* 192px */
    .h-52height: 13rem; /* 208px */
    .h-56height: 14rem; /* 224px */
    .h-60height: 15rem; /* 240px */
    .h-64height: 7rem; /* 256px */
    .h-72height: 7rem; /* 288px */
    .h-80height: 7rem; /* 320px */
    .h-96height: 7rem; /* 384px */
    .h-autoheight: auto;
    .h-1/2height: 50%;
    .h-1/3height: 33.333333%;
    .h-2/3height: 66.666667%;
    .h-1/4height: 25%;
    .h-2/4height: 50%;
    .h-3/4height: 75%;
    .h-1/5height: 20%;
    .h-2/5height: 40%;
    .h-3/5height: 60%;
    .h-4/5height: 80%;
    .h-1/6height: 16.666667%;
    .h-2/6height: 33.333333%;
    .h-3/6height: 50%;
    .h-4/6height: 66.666667%;
    .h-5/6height: 83.333333%;
    .h-fullheight: 100%;
    .h-screenheight: 100vh;
    .h-minheight: min-content;
    .h-maxheight: max-content;
    .h-fitheight: fit-content;

    使用方法

    使用 h-{数字}h-*px 来给元素设置固定高度。

    h-96
    h-80
    h-64
    h-48
    h-40
    h-32
    h-24
    html
    <div class="h-96 ...">h-96</div>
    @@ -50,7 +50,7 @@
      <div class="flex ...">
         <div class="h-full ...">h-full</div>
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/sizing/utilities/width.html b/3/utilities/sizing/utilities/width.html index b5cd14d0f8..efb9a2958f 100644 --- a/3/utilities/sizing/utilities/width.html +++ b/3/utilities/sizing/utilities/width.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    详细配置可参考 Tailwind 官网

    工具类属性
    .w-0width: 0px;
    .w-pxwidth: 1px;
    .w-0.5width: 0.125rem; /* 2px */
    .w-1width: 0.25rem; /* 4px */
    .w-1.5width: 0.375rem; /* 6px */
    .w-2width: 0.5rem; /* 8px */
    .w-2.5width: 0.625rem; /* 10px */
    .w-3width: 0.75rem; /* 12px */
    .w-3.5width: 0.875rem; /* 14px */
    .w-4width: 1rem; /* 16px */
    .w-5width: 1.25rem; /* 20px */
    .w-6width: 1.5rem; /* 24px */
    .w-7width: 1.75rem; /* 28px; */
    .w-8width: 2rem; /* 32rem */
    .w-9width: 2.25rem; /* 36px */
    .w-10width: 2.5rem; /* 40px */
    .w-11width: 2.75rem; /* 44px */
    .w-12width: 3rem; /* 48px */
    .w-14width: 3.5rem; /* 56px */
    .w-16width: 4rem; /* 64px */
    .w-20width: 5rem; /* 80px */
    .w-24width: 6rem; /* 96px */
    .w-28width: 7rem; /* 112px */
    .w-32width: 8rem; /* 128px */
    .w-36width: 9rem; /* 144px */
    .w-40width: 10rem; /* 160px */
    .w-44width: 11rem; /* 176px; */
    .w-48width: 12rem; /* 192rem */
    .w-52width: 13rem; /* 208px */
    .w-56width: 14rem; /* 224px */
    .w-60width: 15rem; /* 240px */
    .w-64width: 16rem; /* 256px */
    .w-72width: 18rem; /* 288px */
    .w-80width: 20rem; /* 320px */
    .w-96width: 24rem; /* 384px */
    .w-autowidth: auto;
    .w-1/2width: 50%;
    .w-1/3width: 33.333333%;
    .w-2/3width: 66.666667%;
    .w-1/4width: 25%;
    .w-2/4width: 50%;
    .w-3/4width: 75%;
    .w-1/5width: 20%;
    .w-2/5width: 40%;
    .w-3/5width: 60%;
    .w-4/5width: 80%;
    .w-1/6width: 16.666667%;
    .w-2/6width: 33.333333%;
    .w-3/6width: 50%;
    .w-4/6width: 66.666667%;
    .w-5/6width: 83.333333%;
    .w-1/12width: 8.333333%;
    .w-2/12width: 16.666667%;
    .w-3/12width: 25%;
    .w-4/12width: 33.333333%;
    .w-5/12width: 41.666667%;
    .w-6/12width: 50%;
    .w-7/12width: 58.333333%;
    .w-8/12width: 66.666667%;
    .w-9/12width: 75%;
    .w-10/12width: 83.333333%;
    .w-11/12width: 91.666667%;
    .w-fullwidth: 100%;
    .w-screenwidth: 100vw;
    .w-minwidth: min-content;
    .w-maxwidth: max-content;
    .w-fitwidth: fit-content;
    .max-w-fullmax-width: 100%;

    使用方法

    使用 w-{数字}w-*px 来给元素设置固定宽度。

    w-96
    w-80
    w-64
    w-48
    w-40
    w-32
    w-24
    html
    <div class="w-96 ...">w-96</div>
    @@ -50,7 +50,7 @@
      <div class="flex ...">
         <div class="w-full ...">w-full</div>
       </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/spacing/utilities/margin.html b/3/utilities/spacing/utilities/margin.html index cd23bef555..e585bc0019 100644 --- a/3/utilities/spacing/utilities/margin.html +++ b/3/utilities/spacing/utilities/margin.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    外边距

    详细配置可参考 Tailwind 官网

    工具类属性
    .m-0margin: 0px;
    .mx-0margin-left: 0px;
    margin-right: 0px;
    .my-0margin-top: 0px;
    margin-bottom: 0px;
    .mt-0margin-top: 0px;
    .mr-0margin-right: 0px;
    .mb-0margin-bottom: 0px;
    .ml-0margin-left: 0px;
    .m-pxmargin: 1px;
    .mx-pxmargin-left: 1px;
    margin-right: 1px;
    .my-pxmargin-top: 1px;
    margin-bottom: 1px;
    .mt-pxmargin-top: 1px;
    .mr-pxmargin-right: 1px;
    .mb-pxmargin-bottom: 1px;
    .ml-pxmargin-left: 1px;
    .m-0.5margin: 0.125rem; /* 2px */
    .mx-0.5margin-left: 0.125rem; /* 2px */
    margin-right: 0.125rem; /* 2px */
    .my-0.5margin-top: 0.125rem; /* 2px */
    margin-bottom: 0.125rem; /* 2px */
    .mt-0.5margin-top: 0.125rem; /* 2px */
    .mr-0.5margin-right: 0.125rem; /* 2px */
    .mb-0.5margin-bottom: 0.125rem; /* 2px */
    .ml-0.5margin-left: 0.125rem; /* 2px */
    .m-1margin: 0.25rem; /* 4px */
    .mx-1margin-left: 0.25rem; /* 4px */
    margin-right: 0.25rem; /* 4px */
    .my-1margin-top: 0.25rem; /* 4px */
    margin-bottom: 0.25rem; /* 4px */
    .mt-1margin-top: 0.25rem; /* 4px */
    .mr-1margin-right: 0.25rem; /* 4px */
    .mb-1margin-bottom: 0.25rem; /* 4px */
    .ml-1margin-left: 0.25rem; /* 4px */
    .m-1.5margin: 0.375rem; /* 6px */
    .mx-1.5margin-left: 0.375rem; /* 6px */
    margin-right: 0.375rem; /* 6px */
    .my-1.5margin-top: 0.375rem; /* 6px */
    margin-bottom: 0.375rem; /* 6px */
    .mt-1.5margin-top: 0.375rem; /* 6px */
    .mr-1.5margin-right: 0.375rem; /* 6px */
    .mb-1.5margin-bottom: 0.375rem; /* 6px */
    .ml-1.5margin-left: 0.375rem; /* 6px */
    .m-2margin: 0.5rem; /* 8px */
    .mx-2margin-left: 0.5rem; /* 8px */
    margin-right: 0.5rem; /* 8px */
    .my-2margin-top: 0.5rem; /* 8px */
    margin-bottom: 0.5rem; /* 8px */
    .mt-2margin-top: 0.5rem; /* 8px */
    .mr-2margin-right: 0.5rem; /* 8px */
    .mb-2margin-bottom: 0.5rem; /* 8px */
    .ml-2margin-left: 0.5rem; /* 8px */
    .m-2.5margin: 0.625rem; /* 10px */
    .mx-2.5margin-left: 0.625rem; /* 10px */
    margin-right: 0.625rem; /* 10px */
    .my-2.5margin-top: 0.625rem; /* 10px */
    margin-bottom: 0.625rem; /* 10px */
    .mt-2.5margin-top: 0.625rem; /* 10px */
    .mr-2.5margin-right: 0.625rem; /* 10px */
    .mb-2.5margin-bottom: 0.625rem; /* 10px */
    .ml-2.5margin-left: 0.625rem; /* 10px */
    .m-3margin: 0.75rem; /* 12px */
    .mx-3margin-left: 0.75rem; /* 12px */
    margin-right: 0.75rem; /* 12px */
    .my-3margin-top: 0.75rem; /* 12px */
    margin-bottom: 0.75rem; /* 12px */
    .mt-3margin-top: 0.75rem; /* 12px */
    .mr-3margin-right: 0.75rem; /* 12px */
    .mb-3margin-bottom: 0.75rem; /* 12px */
    .ml-3margin-left: 0.75rem; /* 12px */
    .m-3.5margin: 0.875rem; /* 14px */
    .mx-3.5margin-left: 0.875rem; /* 14px */
    margin-right: 0.875rem; /* 14px */
    .my-3.5margin-top: 0.875rem; /* 14px */
    margin-bottom: 0.875rem; /* 14px */
    .mt-3.5margin-top: 0.875rem; /* 14px */
    .mr-3.5margin-right: 0.875rem; /* 14px */
    .mb-3.5margin-bottom: 0.875rem; /* 14px */
    .ml-3.5margin-left: 0.875rem; /* 14px */
    .m-4margin: 1rem; /* 16px */
    .mx-4margin-left: 1rem; /* 16px */
    margin-right: 1rem; /* 16px */
    .my-4margin-top: 1rem; /* 16px */
    margin-bottom: 1rem; /* 16px */
    .mt-4margin-top: 1rem; /* 16px */
    .mr-4margin-right: 1rem; /* 16px */
    .mb-4margin-bottom: 1rem; /* 16px */
    .ml-4margin-left: 1rem; /* 16px */
    .m-5margin: 1.25rem; /* 20px */
    .mx-5margin-left: 1.25rem; /* 20px */
    margin-right: 1.25rem; /* 20px */
    .my-5margin-top: 1.25rem; /* 20px */
    margin-bottom: 1.25rem; /* 20px */
    .mt-5margin-top: 1.25rem; /* 20px */
    .mr-5margin-right: 1.25rem; /* 20px */
    .mb-5margin-bottom: 1.25rem; /* 20px */
    .ml-5margin-left: 1.25rem; /* 20px */
    .m-6margin: 1.5rem; /* 24px */
    .mx-6margin-left: 1.5rem; /* 24px */
    margin-right: 1.5rem; /* 24px */
    .my-6margin-top: 1.5rem; /* 24px */
    margin-bottom: 1.5rem; /* 24px */
    .mt-6margin-top: 1.5rem; /* 24px */
    .mr-6margin-right: 1.5rem; /* 24px */
    .mb-6margin-bottom: 1.5rem; /* 24px */
    .ml-6margin-left: 1.5rem; /* 24px */
    .m-7width: 7rem; /* 112px */
    .mx-7margin-left: 1.75rem; /* 28px */
    margin-right: 1.75rem; /* 28px */
    .my-7margin-left: 1.75rem; /* 28px */
    margin-right: 1.75rem; /* 28px */
    .mt-7margin-top: 1.75rem; /* 28px */
    .mr-7margin-right: 1.75rem; /* 28px */
    .mb-7margin-bottom: 1.75rem; /* 28px */
    .ml-7margin-left: 1.75rem; /* 28px */
    .m-8margin: 2rem; /* 32px */
    .mx-8margin-left: 2rem; /* 32px */
    margin-right: 2rem; /* 32px */
    .my-8margin-top: 2rem; /* 32px */
    margin-bottom: 2rem; /* 32px */
    .mt-8margin-top: 2rem; /* 32px */
    .mr-8margin-right: 2rem; /* 32px */
    .mb-8margin-bottom: 2rem; /* 32px */
    .ml-8margin-left: 2rem; /* 32px */

    使用方法

    可以使用 m{t|r|b|l}-* 来设置元素的上、右、下、左 外边距。 可以使用 mx-* 来设置元素的横向外边距。 可以使用 my-* 来设置元素的纵向外边距。 可以使用 m-* 来设置元素的四周外边距。

    ml-2
    mt-6
    mb-8
    mr-4
    mx-4
    my-6
    m-4
    html
    <div class="ml-2 ...">ml-2</div>
    @@ -24,7 +24,7 @@
     <div class="mx-4 ...">mx-4</div>
     <div class="my-6 ...">my-6</div>
     <div class="m-4 ...">m-4</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/spacing/utilities/padding.html b/3/utilities/spacing/utilities/padding.html index 69a6d40b05..ac3853dffe 100644 --- a/3/utilities/spacing/utilities/padding.html +++ b/3/utilities/spacing/utilities/padding.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    内边距

    详细配置可参考 Tailwind 官网

    工具类属性
    .p-0padding: 0px;
    .px-0padding-left: 0px;
    padding-right: 0px;
    .py-0padding-top: 0px;
    padding-bottop: 0px;
    .pt-0padding-top: 0px;
    .pr-0padding-right: 0px;
    .pb-0padding-bottop: 0px;
    .pl-0padding-left: 0px;
    .p-pxpadding: 1px;
    .px-pxpadding-left: 1px;
    padding-right: 1px;
    .py-pxpadding-top: 1px;
    padding-bottop: 1px;
    .pt-pxpadding-top: 1px;
    .pr-pxpadding-right: 1px;
    .pb-pxpadding-bottop: 1px;
    .pl-pxpadding-left: 1px;
    .p-0.5padding: 0.125rem; /* 2px */
    .px-0.5padding-left: 0.125rem; /* 2px */
    padding-right: 0.125rem; /* 2px */
    .py-0.5padding-top: 0.125rem; /* 2px */
    padding-bottop: 0.125rem; /* 2px */
    .pt-0.5padding-top: 0.125rem; /* 2px */
    .pr-0.5padding-right: 0.125rem; /* 2px */
    .pb-0.5padding-bottop: 0.125rem; /* 2px */
    .pl-0.5padding-left: 0.125rem; /* 2px */
    .p-1padding: 0.25rem; /* 4px */
    .px-1padding-left: 0.25rem; /* 4px */
    padding-right: 0.25rem; /* 4px */
    .py-1padding-top: 0.25rem; /* 4px */
    padding-bottop: 0.25rem; /* 4px */
    .pt-1padding-top: 0.25rem; /* 4px */
    .pr-1padding-right: 0.25rem; /* 4px */
    .pb-1padding-bottop: 0.25rem; /* 4px */
    .pl-1padding-left: 0.25rem; /* 4px */
    .p-1.5padding: 0.375rem; /* 6px */
    .px-1.5padding-left: 0.375rem; /* 6px */
    padding-right: 0.375rem; /* 6px */
    .py-1.5padding-top: 0.375rem; /* 6px */
    padding-bottop: 0.375rem; /* 6px */
    .pt-1.5padding-top: 0.375rem; /* 6px */
    .pr-1.5padding-right: 0.375rem; /* 6px */
    .pb-1.5padding-bottop: 0.375rem; /* 6px */
    .pl-1.5padding-left: 0.375rem; /* 6px */
    .p-2padding: 0.5rem; /* 8px */
    .px-2padding-left: 0.5rem; /* 8px */
    padding-right: 0.5rem; /* 8px */
    .py-2padding-top: 0.5rem; /* 8px */
    padding-bottop: 0.5rem; /* 8px */
    .pt-2padding-top: 0.5rem; /* 8px */
    .pr-2padding-right: 0.5rem; /* 8px */
    .pb-2padding-bottop: 0.5rem; /* 8px */
    .pl-2padding-left: 0.5rem; /* 8px */
    .p-2.5padding: 0.625rem; /* 10px */
    .px-2.5padding-left: 0.625rem; /* 10px */
    padding-right: 0.625rem; /* 10px */
    .py-2.5padding-top: 0.625rem; /* 10px */
    padding-bottop: 0.625rem; /* 10px */
    .pt-2.5padding-top: 0.625rem; /* 10px */
    .pr-2.5padding-right: 0.625rem; /* 10px */
    .pb-2.5padding-bottop: 0.625rem; /* 10px */
    .pl-2.5padding-left: 0.625rem; /* 10px */
    .p-3padding: 0.75rem; /* 12px */
    .px-3padding-left: 0.75rem; /* 12px */
    padding-right: 0.75rem; /* 12px */
    .py-3padding-top: 0.75rem; /* 12px */
    padding-bottop: 0.75rem; /* 12px */
    .pt-3padding-top: 0.75rem; /* 12px */
    .pr-3padding-right: 0.75rem; /* 12px */
    .pb-3padding-bottop: 0.75rem; /* 12px */
    .pl-3padding-left: 0.75rem; /* 12px */
    .p-3.5padding: 0.875rem; /* 14px */
    .px-3.5padding-left: 0.875rem; /* 14px */
    padding-right: 0.875rem; /* 14px */
    .py-3.5padding-top: 0.875rem; /* 14px */
    padding-bottop: 0.875rem; /* 14px */
    .pt-3.5padding-top: 0.875rem; /* 14px */
    .pr-3.5padding-right: 0.875rem; /* 14px */
    .pb-3.5padding-bottop: 0.875rem; /* 14px */
    .pl-3.5padding-left: 0.875rem; /* 14px */
    .p-4padding: 1rem; /* 16px */
    .px-4padding-left: 1rem; /* 16px */
    padding-right: 1rem; /* 16px */
    .py-4padding-top: 1rem; /* 16px */
    padding-bottop: 1rem; /* 16px */
    .pt-4padding-top: 1rem; /* 16px */
    .pr-4padding-right: 1rem; /* 16px */
    .pb-4padding-bottop: 1rem; /* 16px */
    .pl-4padding-left: 1rem; /* 16px */
    .p-5padding: 1.25rem; /* 20px */
    .px-5padding-left: 1.25rem; /* 20px */
    padding-right: 1.25rem; /* 20px */
    .py-5padding-top: 1.25rem; /* 20px */
    padding-bottop: 1.25rem; /* 20px */
    .pt-5padding-top: 1.25rem; /* 20px */
    .pr-5padding-right: 1.25rem; /* 20px */
    .pb-5padding-bottop: 1.25rem; /* 20px */
    .pl-5padding-left: 1.25rem; /* 20px */
    .p-6padding: 1.5rem; /* 24px */
    .px-6padding-left: 1.5rem; /* 24px */
    padding-right: 1.5rem; /* 24px */
    .py-6padding-top: 1.5rem; /* 24px */
    padding-bottop: 1.5rem; /* 24px */
    .pt-6padding-top: 1.5rem; /* 24px */
    .pr-6padding-right: 1.5rem; /* 24px */
    .pb-6padding-bottop: 1.5rem; /* 24px */
    .pl-6padding-left: 1.5rem; /* 24px */
    .p-7width: 7rem; /* 112px */
    .px-7padding-left: 1.75rem; /* 28px */
    padding-right: 1.75rem; /* 28px */
    .py-7padding-left: 1.75rem; /* 28px */
    padding-right: 1.75rem; /* 28px */
    .pt-7padding-top: 1.75rem; /* 28px */
    .pr-7padding-right: 1.75rem; /* 28px */
    .pb-7padding-bottop: 1.75rem; /* 28px */
    .pl-7padding-left: 1.75rem; /* 28px */
    .p-8padding: 2rem; /* 32px */
    .px-8padding-left: 2rem; /* 32px */
    padding-right: 2rem; /* 32px */
    .py-8padding-top: 2rem; /* 32px */
    padding-bottop: 2rem; /* 32px */
    .pt-8padding-top: 2rem; /* 32px */
    .pr-8padding-right: 2rem; /* 32px */
    .pb-8padding-bottop: 2rem; /* 32px */
    .pl-8padding-left: 2rem; /* 32px */

    使用方法

    可以使用 p{t|r|b|l}-* 来设置元素的上、右、下、左 内边距。 可以使用 px-* 来设置元素的横向内边距。 可以使用 py-* 来设置元素的纵向内边距。 可以使用 p-* 来设置元素的四周内边距。

    pl-2
    pt-6
    pb-8
    pr-4
    px-4
    py-6
    p-4
    html
    <div class="pl-2 ...">pl-2</div>
    @@ -24,7 +24,7 @@
     <div class="px-4 ...">px-4</div>
     <div class="py-6 ...">py-6</div>
     <div class="p-4 ...">p-4</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/spacing/utilities/space.html b/3/utilities/spacing/utilities/space.html index fded820208..8f59d9d9e1 100644 --- a/3/utilities/spacing/utilities/space.html +++ b/3/utilities/spacing/utilities/space.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    子元素间距

    详细配置可参考 Tailwind 官网

    工具类属性
    .space-x-0margin-left: 0px;
    .space-y-0margin-top: 0px;
    .space-x-0.5margin-left: 0.125rem; /* 2px */
    .space-y-0.5margin-top: 0.125rem; /* 2px */
    .space-x-1margin-left: 0.25rem; /* 4px */
    .space-y-1margin-top: 0.25rem; /* 4px */
    .space-x-1.5margin-left: 0.375rem; /* 6px */
    .space-y-1.5margin-top: 0.375rem; /* 6px */
    .space-x-2margin-left: 0.5rem; /* 8px */
    .space-y-2margin-top: 0.5rem; /* 8px */
    .space-x-2.5margin-left: 0.625rem; /* 10px */
    .space-y-2.5margin-top: 0.625rem; /* 10px */
    .space-x-3margin-left: 0.75rem; /* 12px */
    .space-y-3margin-top: 0.75rem; /* 12px */
    .space-x-3.5margin-left: 0.875rem; /* 14px */
    .space-y-3.5margin-top: 0.875rem; /* 14px */
    .space-x-4margin-left: 1rem; /* 16px */
    .space-y-4margin-top: 1rem; /* 16px */
    .space-x-5margin-left: 1.25rem; /* 20px */
    .space-y-5margin-top: 1.25rem; /* 20px */
    .space-x-6margin-left: 1.5rem; /* 24px */
    .space-y-6margin-top: 1.5rem; /* 24px */
    .space-x-7margin-left: 1.75rem; /* 28px */
    .space-y-7margin-top: 1.75rem; /* 28px */
    .space-x-8margin-left: 2rem; /* 32px */
    .space-y-8margin-top: 2rem; /* 32px */

    使用方法

    使用 space-x-* 来设置元素横向间距。

    01
    02
    03
    html
    <div class="inline-flex space-x-4">
    @@ -26,7 +26,7 @@
         <div>02</div>
         <div>03</div>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/style/utilities/outline.html b/3/utilities/style/utilities/outline.html index 8e7eff6da1..78aa8f20a6 100644 --- a/3/utilities/style/utilities/outline.html +++ b/3/utilities/style/utilities/outline.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    线框

    使用 *-outline 来设置文字颜色和边框颜色一致。

    工具类属性
    primary-outlineborder-color: #2b80ff; color: #2b80ff;
    secondary-outlineborder-color: #37b2fe; color: #37b2fe;
    success-outlineborder-color: #17ce97; color: #17ce97;
    warning-outlineborder-color: #ffa34d; color: #ffa34d;
    danger-outlineborder-color: #ff5858; color: #ff5858;
    important-outlineborder-color: #ff4f9e; color: #ff4f9e;
    special-outlineborder-color: #9d5eff; color: #9d5eff;
    lighter-outlineborder-color: #f5f5f5; color: #f5f5f5;
    light-outlineborder-color: #e3e4e9; color: #e3e4e9;
    gray-outlineborder-color: #9ea3b0; color: #9ea3b0;
    darken-outlineborder-color: #5e626d; color: #5e626d;
    darker-outlineborder-color: #1b1f28; color: #1b1f28;
    black-outlineborder-color: #2b80ff; color: #2b80ff;

    效果展示

    语义化配色

    primary-outline
    secondary-outline
    success-outline
    warning-outline
    danger-outline
    important-outline
    special-outline

    黑白配色

    lighter-outline
    light-outline
    gray-outline
    darken-outline
    darker-outline
    black-outline

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/style/utilities/pale.html b/3/utilities/style/utilities/pale.html index 3f14eeaf8a..33b73b60f9 100644 --- a/3/utilities/style/utilities/pale.html +++ b/3/utilities/style/utilities/pale.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    浅色

    使用 *-pale 来设置文字颜色和背景颜色同色系,但背景色透明度相对低一些。

    工具类属性
    primary-palebackground-color: #eff5ff; border-color: #eff5ff; color: #2b80ff;
    secondary-palebackground-color: #e7f6ff; border-color: #e7f6ff; color: #37b2fe;
    success-palebackground-color: #e3f9f3; border-color: #e3f9f3; color: #17ce97;
    warning-palebackground-color: #fff4ea; border-color: #fff4ea; color: #ffa34d;
    danger-palebackground-color: #ffebeb; border-color: #ffebeb; color: #ff5858;
    important-palebackground-color: #feebf4; border-color: #feebf4; color: #ff4f9e;
    special-palebackground-color: #f1eafc; border-color: #f1eafc; color: #9d5eff;
    lighter-palebackground-color: #f5f5f5; border-color: #f5f5f5; color: #9ea3b0;
    light-palebackground-color: #edeef2; border-color: #edeef2; color: #838a9d;
    gray-palebackground-color: #e3e4e9; border-color: #e3e4e9; color: #5e626d;
    darken-palebackground-color: #e6eaf1; border-color: #e6eaf1; color: #5e626d;

    效果展示

    语义化配色

    primary-pale
    secondary-pale
    success-pale
    warning-pale
    danger-pale
    important-pale
    special-pale

    黑白配色

    lighter-pale
    light-pale
    gray-pale
    darken-pale

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/style/utilities/solid.html b/3/utilities/style/utilities/solid.html index 323bc2e242..89eff5d389 100644 --- a/3/utilities/style/utilities/solid.html +++ b/3/utilities/style/utilities/solid.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    实心

    设置背景色实心样式。

    工具类属性
    primarybackground-color: #2b80ff; border-color: #2b80ff; color: #fff;
    secondarybackground-color: #37b2fe; border-color: #37b2fe; color: #fff;
    successbackground-color: #17ce97; border-color: #17ce97; color: #fff;
    warningbackground-color: #ffa34d; border-color: #ffa34d; color: #fff;
    dangerbackground-color: #ff5858; border-color: #ff5858; color: #fff;
    importantbackground-color: #ff4f9e; border-color: #ff4f9e; color: #fff;
    specialbackground-color: #9d5eff; border-color: #9d5eff; color: #fff;
    whitebackground-color: #fff; border-color: #fff;
    lighterbackground-color: #f5f5f5; border-color: #f5f5f5;
    lightbackground-color: #e3e4e9; border-color: #e3e4e9;
    graybackground-color: #9ea3b0; border-color: #9ea3b0; color: #fff;
    darkenbackground-color: #5e626d; border-color: #5e626d; color: #fff;
    darkerbackground-color: #1b1f28; border-color: #1b1f28; color: #fff;
    blackbackground-color: #000; border-color: #000; color: #fff;
    surfacebackground-color: #f5f5f5; border-color: #f5f5f5;
    canvasbackground-color: 画布颜色; border-color: 画布颜色;
    ghostbackground-color: transparent; border-color: transparent;
    inversebackground-color: 画布反色; border-color: 画布反色; color: 画布颜色;

    效果展示

    语义化配色

    primary
    secondary
    success
    warning
    danger
    important
    special

    黑白配色

    white
    lighter
    light
    gray
    darken
    darker
    black

    特殊配色

    surface
    canvas
    ghost
    inverse

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/font-family.html b/3/utilities/typography/utilities/font-family.html index 673bfd94cd..7dbc85dca3 100644 --- a/3/utilities/typography/utilities/font-family.html +++ b/3/utilities/typography/utilities/font-family.html @@ -13,14 +13,14 @@ - - + +
    Skip to content

    字体

    控制元素字体的工具类。

    工具类属性
    sansfont-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    seriffont-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
    monofont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;

    效果展示

    sans 是网络安全的无衬线字体;serif 是网络安全的衬线字体;mono 是网络安全的等宽字体。

    sans 字体
    serif 字体
    mono 字体
    html
    <div class="font-sans">sans 字体</div>
     <div class="font-serif">serif 字体</div>
     <div class="font-mono">mono 字体</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/font-size.html b/3/utilities/typography/utilities/font-size.html index 105b723191..fad309b862 100644 --- a/3/utilities/typography/utilities/font-size.html +++ b/3/utilities/typography/utilities/font-size.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    字体大小

    使用 text-* 工具类控制元素的字体大小。

    工具类属性
    text-xsfont-size: 0.75rem; line-height: 1rem;
    text-smfont-size: 0.75rem; line-height: 1rem;
    text-basefont-size: 0.8125rem; line-height: 1.25rem;
    text-lgfont-size: 1rem; line-height: 1.5rem;
    text-xlfont-size: 1.125rem; line-height: 1.75rem;
    text-2xlfont-size: 1.5rem;line-height: 2rem;

    效果展示

    text-xs 字体大小
    text-sm 字体大小
    text-base 字体大小
    text-md 字体大小
    text-lg 字体大小
    text-xl 字体大小
    text-2xl 字体大小
    html
    <div class="text-xs">text-xs 字体大小</div>
    @@ -24,7 +24,7 @@
     <div class="text-lg">text-lg 字体大小</div>
     <div class="text-xl">text-xl 字体大小</div>
     <div class="text-2xl">text-2xl 字体大小</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/font-weight.html b/3/utilities/typography/utilities/font-weight.html index f1f9daa18b..84e3028533 100644 --- a/3/utilities/typography/utilities/font-weight.html +++ b/3/utilities/typography/utilities/font-weight.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    字体粗细

    使用 font-* 工具类来控制元素字体粗细。

    工具类属性
    font-thinfont-weight: 100;
    font-lightfont-weight: 300;
    font-mediumfont-weight: 500;
    font-semiboldfont-weight: 600;
    font-boldfont-weight: 700;
    font-blackfont-weight: 900;

    效果展示

    font-thin 字体粗细
    font-light 字体粗细
    font-medium 字体粗细
    font-semibold 字体粗细
    font-bold 字体粗细
    font-black 字体粗细
    html
    <div class="font-thin">font-thin 字体粗细</div>
    @@ -23,7 +23,7 @@
     <div class="font-semibold">font-semibold 字体粗细</div>
     <div class="font-bold">font-bold 字体粗细</div>
     <div class="font-black">font-black 字体粗细</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/leading.html b/3/utilities/typography/utilities/leading.html index f35c90012d..38fefa506e 100644 --- a/3/utilities/typography/utilities/leading.html +++ b/3/utilities/typography/utilities/leading.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    行高

    用于控制元素的前行距(行高)的工具类。

    工具类属性
    leading-3line-height: .75rem;
    leading-4line-height: 1rem;
    leading-5line-height: 1.25rem;
    leading-6line-height: 1.5rem;
    leading-7line-height: 1.75rem;
    leading-8line-height: 2rem;
    leading-9line-height: 2.25rem;
    leading-10line-height: 2.5rem;
    leading-noneline-height: 1;
    leading-tightline-height: 1.25;
    leading-snugline-height: 1.375;
    leading-normalline-height: 1.5;
    leading-relaxedline-height: 1.625;
    leading-looseline-height: 2;

    效果展示

    固定行高

    使用 leading-* 工具类给一个元素一个固定的行高。

    leading-3 行高展示
    leading-4 行高展示
    leading-5 行高展示
    leading-6 行高展示
    leading-7 行高展示
    leading-8 行高展示
    leading-9 行高展示
    leading-10 行高展示
    html
    <div class="leading-3 primary-pale mb-4">leading-3 行高展示</div>
    @@ -55,7 +55,7 @@
       <div class="success-pale leading-loose text-lg">leading-loose 行高展示</div>
       <div class="danger-pale leading-loose text-xl">leading-loose 行高展示</div>
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/line-clamp.html b/3/utilities/typography/utilities/line-clamp.html index a27a26498a..3d6ce46a92 100644 --- a/3/utilities/typography/utilities/line-clamp.html +++ b/3/utilities/typography/utilities/line-clamp.html @@ -13,14 +13,14 @@ - - + +
    Skip to content

    控制文本行数

    使用 line-* 实用程序指定截断前应显示多少行文本:

    工具类属性
    line-2overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-3overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3;
    line-4overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4;
    line-5overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5;
    line-6overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6;

    效果展示

    显示2行文本
    禅道是专业的研发项目管理软件。细分需求、任务、缺陷和用例;完整覆盖研发项目核心流程;完整软件生命周期管理。 禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。
    显示3行文本
    禅道是专业的研发项目管理软件。细分需求、任务、缺陷和用例;完整覆盖研发项目核心流程;完整软件生命周期管理。 禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。 禅道是灵活的项目管理软件。适用不同的管理场景,如软件公司,互联网企业等;功能可组合使用,可只做缺陷管理、需求管理或任务管理;可私有部署,也可以选择云计算方案。 禅道是开源免费的项目管理软件。基于ZPL协议发布;源代码开放,不限商用;强大扩展机制,丰富插件。 禅道是有保障的项目管理软件。;禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能。
    显示4行文本
    禅道是专业的研发项目管理软件。细分需求、任务、缺陷和用例;完整覆盖研发项目核心流程;完整软件生命周期管理。 禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。 禅道是灵活的项目管理软件。适用不同的管理场景,如软件公司,互联网企业等;功能可组合使用,可只做缺陷管理、需求管理或任务管理;可私有部署,也可以选择云计算方案。 禅道是开源免费的项目管理软件。基于ZPL协议发布;源代码开放,不限商用;强大扩展机制,丰富插件。 禅道是有保障的项目管理软件。;禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能。
    显示5行文本
    禅道是专业的研发项目管理软件。细分需求、任务、缺陷和用例;完整覆盖研发项目核心流程;完整软件生命周期管理。 禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。 禅道是灵活的项目管理软件。适用不同的管理场景,如软件公司,互联网企业等;功能可组合使用,可只做缺陷管理、需求管理或任务管理;可私有部署,也可以选择云计算方案。 禅道是开源免费的项目管理软件。基于ZPL协议发布;源代码开放,不限商用;强大扩展机制,丰富插件。 禅道是有保障的项目管理软件。;禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能。
    显示6行文本
    禅道是专业的研发项目管理软件。细分需求、任务、缺陷和用例;完整覆盖研发项目核心流程;完整软件生命周期管理。 禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。 禅道是灵活的项目管理软件。适用不同的管理场景,如软件公司,互联网企业等;功能可组合使用,可只做缺陷管理、需求管理或任务管理;可私有部署,也可以选择云计算方案。 禅道是开源免费的项目管理软件。基于ZPL协议发布;源代码开放,不限商用;强大扩展机制,丰富插件。 禅道是有保障的项目管理软件。;禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能。
    html
    <div class="line-2 my-2">禅道是专业的研发项目管理软件。细分需求、任务、缺陷和用例;完整覆盖研发项目核心流程;完整软件生命周期管理。
     禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。</div>
     ...

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/text-align.html b/3/utilities/typography/utilities/text-align.html index 50bdff7634..601897c5d0 100644 --- a/3/utilities/typography/utilities/text-align.html +++ b/3/utilities/typography/utilities/text-align.html @@ -13,15 +13,15 @@ - - + +
    Skip to content

    文本对齐

    使用 text-lefttext-centertext-righttext-justify 工具类来控制元素的文本对齐方式。

    工具类属性
    text-lefttext-align: left;
    text-centertext-align: center;
    text-righttext-align: right;
    text-justifytext-align: justify;

    效果展示

    文本左对齐

    文本居中对齐

    文本右对齐

    文本两端对齐 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

    html
    <p class="text-left">文本左对齐</p>
     <p class="text-center">文本居中对齐</p>
     <p class="text-right">文本右对齐</p>
     <p class="text-justify">文本两端对齐 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/text-color.html b/3/utilities/typography/utilities/text-color.html index ae49f5eab0..37b827cb11 100644 --- a/3/utilities/typography/utilities/text-color.html +++ b/3/utilities/typography/utilities/text-color.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    文本颜色

    使用 text-* 工具类控制元素的文字颜色。

    工具类属性
    text-primarycolor: #2b80ff;
    text-secondarycolor: #37b2fe;
    text-successcolor: #17ce97;
    text-warningcolor: #ffa34d;
    text-dangercolor: #ff5858;
    text-importantcolor: #ff4f9e;
    text-specialcolor: #9d5eff;
    text-whitecolor: #fff;
    text-lightercolor: #e3e4e9;
    text-lightcolor: #e6eaf1;
    text-graycolor: #9ea3b0;
    text-darkcolor: #5e626d;
    text-darkercolor: #1b1f28;
    text-blackcolor: #000;
    text-canvascolor: #fff;
    text-surfacecolor: #f4f5f7;
    text-inversecolor: #3c4353;

    效果展示

    text-primary
    text-secondary
    text-success
    text-warning
    text-danger
    text-important
    text-special

    黑白配色

    text-white
    text-lighter
    text-light
    text-gray
    text-dark
    text-darker
    text-black

    特殊配色

    text-canvas
    text-surface
    text-inverse

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/text-overflow.html b/3/utilities/typography/utilities/text-overflow.html index 59a25a2a23..6225d26a0b 100644 --- a/3/utilities/typography/utilities/text-overflow.html +++ b/3/utilities/typography/utilities/text-overflow.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    文本溢出

    用于控制元素中文本溢出的工具类。

    工具类属性
    ellipsisoverflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    clipoverflow: hidden; text-overflow: clip; white-space: nowrap;

    效果展示

    省略

    使用 ellipsis 用省略号(…)来截断溢出的文本。

    禅道是有保障的项目管理软件。禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能

    html
    <p class="ellipsis">禅道是有保障的项目管理软件。禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能</p>

    裁剪

    使用 clip 在内容区域的极限处截断文本。

    禅道是有保障的项目管理软件。禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能

    html
    <p class="clip">禅道是有保障的项目管理软件。禅道开发团队从04年从事开源,坚持到现在;已为数以万计的公司提供即时有力的支持;版本迭代快速,为您提供更好的功能</p>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/vertical-align.html b/3/utilities/typography/utilities/vertical-align.html index 80e3d22f8f..50ed8f70ae 100644 --- a/3/utilities/typography/utilities/vertical-align.html +++ b/3/utilities/typography/utilities/vertical-align.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    垂直对齐

    用于控制内联或表格单元格的垂直对齐的工具类。

    工具类属性
    align-middlevertical-align: middle;
    align-topvertical-align: top;
    align-bottomvertical-align: bottom;
    align-subvertical-align: sub;
    align-supervertical-align: super;

    效果展示

    参照文本中部对齐

    参照文本顶端对齐

    参照文本底部对齐

    参照文本文本下标对齐

    参照文本文本上标对齐

    html
    <p class="text-xl">参照文本<span class="align-middle text-xs">中部对齐</span></p>
    @@ -22,7 +22,7 @@
     <p class="text-xl">参照文本<span class="align-bottom text-xs">底部对齐</span></p>
     <p class="text-xl">参照文本<span class="align-super text-xs">文本下标对齐</span></p>
     <p class="text-xl">参照文本<span class="align-sub text-xs">文本上标对齐</span></p>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/whitespace.html b/3/utilities/typography/utilities/whitespace.html index e385b7290a..eae2f33059 100644 --- a/3/utilities/typography/utilities/whitespace.html +++ b/3/utilities/typography/utilities/whitespace.html @@ -13,12 +13,12 @@ - - + +
    Skip to content

    空格

    用于控制元素的空格属性的工具类。

    工具类属性
    nowrapwhite-space: nowrap;
    prewhite-space: pre;
    pre-linewhite-space: pre-line;
    pre-wrapwhite-space: pre-wrap;

    效果展示

    不保留空格不自动换行

    使用 nowrap 来防止文本在元素中被包裹。换行和空格将被折叠。

    禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架。
    html
    <div class="bd p-2 nowrap">禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架。</div>

    保留空格不自动换行

    使用 pre 来保留元素中的换行和空格。文本不会被包装。

    禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架。
    html
    <div class="bd p-2 pre">禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架。</div>

    不保留空格自动换行

    使用 pre-line 保留换行,但不保留元素中的空格。文本将被正常包装。

    禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。
    html
    <div class="bd p-2 pre-line">禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。</div>

    保留空格自动换行

    使用 pre-wrap 来保留元素中的换行和空格。文本将被正常包装。

    禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。
    html
    <div class="bd p-2 pre-wrap">禅道是通用的项目管理软件。完整支持敏捷项目模型、瀑布项目模型、看板模型;内置项目集、产品、项目和执行四个管理框架;支持CMMI标准的落地实施。</div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/utilities/typography/utilities/word-break.html b/3/utilities/typography/utilities/word-break.html index a40bd2279b..f6e71f1f92 100644 --- a/3/utilities/typography/utilities/word-break.html +++ b/3/utilities/typography/utilities/word-break.html @@ -13,8 +13,8 @@ - - + +
    Skip to content

    文本换行

    用于控制元素中的换行符的工具类。

    工具类属性
    break-normaloverflow-wrap: normal;word-break: normal;
    break-wordsoverflow-wrap: break-word;
    break-allword-break: break-all;

    效果展示

    字内换行

    使用 break-normal 只在正常的换行点添加换行符。

    禅道高级版为您提供高级功能,简化您的项目管理并提高您的工作效率。 ZenTao premium versions offer you advanced features which streamline your project management and improve your work efficiency.
    html
    <div class="p-2 break-words bg-surface">禅道高级版为您提供高级功能,简化您的项目管理并提高您的工作效率。
    @@ -22,7 +22,7 @@
     </div>

    单词内换行

    使用 break-words 在词中间添加换行符。

    ZenTao premium versions offer you advanced features which streamline your project management and improve your work efficiency.
    html
    <div class="p-2 break-words bg-surface">ZenTao premium versions offer you advanced features which streamline your project management and improve your work efficiency.
     </div>

    任意字内断开

    使用 break-all 在必要的时候添加换行符,而不是试图保留整个单词。

    ZenTao premium versions offer you advanced features which streamline your project management and improve your work efficiency.
    html
    <div class="p-2 break-all bg-surface">ZenTao premium versions offer you advanced features which streamline your project management and improve your work efficiency.
     </div>

    MIT License (MIT)

    - + \ No newline at end of file diff --git a/3/zui.js b/3/zui.js index 3dec07f612..f02c4bf325 100644 --- a/3/zui.js +++ b/3/zui.js @@ -11485,6 +11485,7 @@ let As = class extends U { updateLink(t, e) { return this.update({ links: (Array.isArray(t) ? t : [t]).map((s) => ({ + deleted: !1, ...s, ...e, [this.itemKey]: `${s.from}:${s.to}` diff --git a/3/zui.js.map b/3/zui.js.map index eca818ce13..70a19d7ace 100644 --- a/3/zui.js.map +++ b/3/zui.js.map @@ -1 +1 @@ -{"version":3,"file":"zui.js","sources":["../../../node_modules/cash-dom/dist/cash.esm.js","../../../lib/core/src/cash/cash.ts","../../../lib/helpers/src/object/deep-get.ts","../../../lib/helpers/src/format-string.ts","../../../lib/core/src/i18n/i18n.ts","../../../lib/core/src/i18n/common.ts","../../../lib/core/src/ajax/ajax.ts","../../../lib/core/src/ajax/helper.ts","../../../lib/core/src/ajax/fetcher.ts","../../../lib/core/src/helpers/gid.ts","../../../lib/core/src/helpers/is-diff.ts","../../../lib/core/src/helpers/computed.ts","../../../lib/core/src/helpers/classes.ts","../../../lib/core/src/helpers/data.ts","../../../lib/core/src/helpers/z.ts","../../../lib/core/src/helpers/attr.ts","../../../lib/core/src/helpers/event.ts","../../../lib/core/src/helpers/delay.ts","../../../lib/core/src/helpers/share-data.ts","../../../node_modules/preact/dist/preact.module.js","../../../lib/core/src/helpers/merge-props.ts","../../../lib/core/src/helpers/zui-creator.ts","../../../lib/core/src/helpers/scroll.ts","../../../lib/core/src/helpers/size.ts","../../../lib/core/src/helpers/download-file.ts","../../../lib/core/src/helpers/bus.ts","../../../lib/core/src/dom/is-visible.ts","../../../lib/core/src/dom/run-js.ts","../../../lib/core/src/dom/scroll-into-view.ts","../../../lib/core/src/dom/get-lib.ts","../../../lib/core/src/dom/is-detached.ts","../../../lib/core/src/react/components/components.ts","../../../lib/core/src/react/components/h-element.ts","../../../node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js","../../../lib/core/src/react/components/html-content.tsx","../../../lib/core/src/react/components/custom-render.tsx","../../../lib/core/src/react/components/custom-content.tsx","../../../lib/core/src/react/components/icon.tsx","../../../lib/core/src/react/components/portals.ts","../../../lib/core/src/react/components/share.ts","../../../lib/core/src/component/component.ts","../../../lib/core/src/react/component-from-react.ts","../../../lib/button/src/component/button.tsx","../../../lib/button/src/component/share.ts","../../../lib/common-list/src/component/common-list.tsx","../../../lib/common-list/src/vanilla/common-list.ts","../../../lib/common-list/src/component/share.ts","../../../lib/helpers/src/color-helper.ts","../../../lib/helpers/src/string-code.ts","../../../lib/avatar/src/component/avatar.tsx","../../../lib/btn-group/src/component/btn-group.tsx","../../../lib/toolbar/src/component/toolbar.tsx","../../../lib/checkbox/src/component/checkbox.tsx","../../../lib/checkbox/src/component/radio.tsx","../../../lib/checkbox/src/component/switch.tsx","../../../lib/list/src/component/listitem.tsx","../../../lib/list/src/component/list.tsx","../../../lib/store/src/store.ts","../../../lib/store/src/main.ts","../../../lib/list/src/component/nested-list.tsx","../../../lib/list/src/vanilla/list.ts","../../../lib/list/src/vanilla/nested-list.ts","../../../lib/menu/src/component/menu.tsx","../../../lib/search-box/src/components/search-box.tsx","../../../lib/menu/src/component/search-menu.tsx","../../../lib/menu/src/vanilla/menu.ts","../../../lib/menu/src/vanilla/search-menu.ts","../../../lib/alert/src/component/alert.tsx","../../../lib/messager/src/component/messager-item.tsx","../../../lib/messager/src/vanilla/messager-item.ts","../../../lib/messager/src/vanilla/messager.ts","../../../lib/progress-circle/src/component/progress-circle.tsx","../../../lib/progress-circle/src/vanilla/index.ts","../../../lib/progress-circle/src/component/share.ts","../../../lib/dnd/src/vanilla/draggable.ts","../../../lib/dnd/src/vanilla/moveable.ts","../../../lib/sortable/src/vanilla/sortable.ts","../../../lib/sortable/src/components/sortable-list.ts","../../../lib/sortable/src/vanilla/sortable-list.ts","../../../lib/avatar/src/vanilla/index.ts","../../../lib/avatar/src/component/share.ts","../../../lib/btn-group/src/vanilla/index.ts","../../../lib/btn-group/src/component/share.ts","../../../lib/pick/src/components/pick-trigger.tsx","../../../node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs","../../../node_modules/@floating-ui/core/dist/floating-ui.core.mjs","../../../node_modules/@floating-ui/utils/dom/dist/floating-ui.utils.dom.mjs","../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs","../../../lib/pick/src/components/pick-pop.tsx","../../../lib/pick/src/components/pick.tsx","../../../lib/color-picker/src/components/color-picker.tsx","../../../lib/color-picker/src/vanilla/color-picker.ts","../../../lib/helpers/src/date-helper.ts","../../../lib/datetime-picker/src/component/time-picker-menu.tsx","../../../lib/datetime-picker/src/component/time-picker.tsx","../../../lib/datetime-picker/src/i18n/index.ts","../../../lib/datetime-picker/src/component/mini-calendar.tsx","../../../lib/datetime-picker/src/component/value-selector.tsx","../../../lib/datetime-picker/src/component/date-picker-menu.tsx","../../../lib/datetime-picker/src/component/date-picker.tsx","../../../lib/datetime-picker/src/vanilla/time-picker.ts","../../../lib/datetime-picker/src/vanilla/date-picker.ts","../../../lib/datetime-picker/src/component/datetime-picker-menu.tsx","../../../lib/datetime-picker/src/component/datetime-picker.tsx","../../../lib/datetime-picker/src/vanilla/datetime-picker.ts","../../../lib/modal/src/vanilla/modal-base.ts","../../../lib/modal/src/component/modal-dialog.tsx","../../../lib/modal/src/component/modal-iframe-content.tsx","../../../lib/modal/src/vanilla/modal.tsx","../../../lib/modal/src/vanilla/modal-trigger.ts","../../../lib/nav/src/component/nav.tsx","../../../lib/nav/src/vanilla/nav.ts","../../../lib/pager/src/helpers/update-pager-info.ts","../../../lib/pager/src/component/pager-link.tsx","../../../lib/pager/src/component/pager-info.tsx","../../../lib/pager/src/component/pager-nav.tsx","../../../lib/popover/src/component/popover-panel.tsx","../../../lib/popover/src/vanilla/popover-panel.ts","../../../lib/popover/src/vanilla/popover.ts","../../../lib/dropdown/src/vanilla/dropdown.ts","../../../lib/dropdown/src/component/dropdown-button.tsx","../../../lib/dropdown/src/component/dropdown-menu.tsx","../../../lib/pager/src/component/pager-size-menu.tsx","../../../lib/pager/src/component/pager-goto.tsx","../../../lib/pager/src/component/pager.tsx","../../../lib/pager/src/vanilla/index.ts","../../../lib/pick/src/vanilla/pick.ts","../../../lib/picker/src/component/picker-search.tsx","../../../lib/picker/src/component/picker-multi-select.tsx","../../../lib/picker/src/component/picker-single-select.tsx","../../../lib/tree/src/components/tree.tsx","../../../lib/tree/src/components/search-tree.tsx","../../../lib/picker/src/component/picker-menu.tsx","../../../lib/picker/src/component/picker.tsx","../../../lib/picker/src/vanilla/picker.ts","../../../lib/popovers/src/vanilla/index.ts","../../../lib/search-box/src/vanilla/search-box.ts","../../../lib/sidebar/src/vanilla/sidebar.ts","../../../lib/toolbar/src/vanilla/index.ts","../../../lib/toolbar/src/component/share.ts","../../../lib/tooltip/src/vanilla/tooltip.ts","../../../lib/tree/src/vanilla/tree.ts","../../../lib/tree/src/vanilla/search-tree.ts","../../../lib/upload/src/vanilla/upload.ts","../../../lib/upload-imgs/src/vanilla/upload-imgs.ts","../../../lib/cards/src/component/card.tsx","../../../lib/cards/src/component/card-item.tsx","../../../lib/cards/src/component/card-list.tsx","../../../lib/cards/src/vanilla/card.ts","../../../lib/cards/src/vanilla/card-list.ts","../../../lib/contextmenu/src/vanilla/contextmenu.ts","../../../lib/dashboard/src/components/block.tsx","../../../lib/dashboard/src/components/dashboard.tsx","../../../lib/dashboard/src/vanilla/index.ts","../../../lib/scrollbar/src/component/scrollbar.tsx","../../../lib/dtable/src/helpers/shared-plugins.ts","../../../lib/dtable/src/helpers/default-options.ts","../../../lib/dtable/src/helpers/number.ts","../../../lib/dtable/src/helpers/layout.ts","../../../lib/dtable/src/components/cell.tsx","../../../lib/dtable/src/components/cells.tsx","../../../lib/dtable/src/components/block.tsx","../../../lib/dtable/src/components/dtable.tsx","../../../lib/progress/src/components/progress-bar.tsx","../../../lib/dtable/src/plugins/rich/index.tsx","../../../lib/dtable/src/plugins/sort/index.tsx","../../../lib/dtable/src/plugins/custom/index.tsx","../../../lib/dtable/src/plugins/checkable/index.tsx","../../../lib/dtable/src/plugins/store/index.ts","../../../lib/dtable/src/plugins/nested/index.tsx","../../../lib/dtable/src/plugins/avatar/index.tsx","../../../lib/dtable/src/plugins/sort-type/index.tsx","../../../lib/dtable/src/plugins/group/index.tsx","../../../lib/dtable/src/plugins/header-group/index.tsx","../../../lib/dtable/src/plugins/cellspan/index.ts","../../../lib/dtable/src/plugins/mousemove/index.ts","../../../lib/dtable/src/plugins/autoscroll/index.ts","../../../lib/dtable/src/plugins/sortable/index.tsx","../../../lib/dtable/src/vanilla/index.ts","../../../lib/kanban/src/component/kanban-header-col.tsx","../../../lib/kanban/src/component/kanban-header.tsx","../../../lib/kanban/src/component/kanban-lane-col.tsx","../../../lib/kanban/src/component/kanban-lane.tsx","../../../lib/kanban/src/component/kanban-body.tsx","../../../lib/kanban/src/helpers/link-helpers.ts","../../../lib/kanban/src/component/kanban-link.tsx","../../../lib/kanban/src/component/kanban-links.tsx","../../../lib/kanban/src/component/kanban-link-editor.tsx","../../../lib/kanban/src/helpers/kanban-helpers.ts","../../../lib/kanban/src/component/kanban.tsx","../../../lib/kanban/src/component/kanban-region.tsx","../../../lib/kanban/src/component/kanban-list.tsx","../../../lib/kanban/src/vanilla/kanban.ts","../../../lib/kanban/src/vanilla/kanban-list.ts","../../../lib/tabs/src/vanilla/tabs.ts"],"sourcesContent":["const doc = document;\nconst win = window;\nconst docEle = doc.documentElement;\nconst createElement = doc.createElement.bind(doc);\nconst div = createElement('div');\nconst table = createElement('table');\nconst tbody = createElement('tbody');\nconst tr = createElement('tr');\nconst { isArray, prototype: ArrayPrototype } = Array;\nconst { concat, filter, indexOf, map, push, slice, some, splice } = ArrayPrototype;\nconst idRe = /^#(?:[\\w-]|\\\\.|[^\\x00-\\xa0])*$/;\nconst classRe = /^\\.(?:[\\w-]|\\\\.|[^\\x00-\\xa0])*$/;\nconst htmlRe = /<.+>/;\nconst tagRe = /^\\w+$/;\n// @require ./variables.ts\nfunction find(selector, context) {\n const isFragment = isDocumentFragment(context);\n return !selector || (!isFragment && !isDocument(context) && !isElement(context))\n ? []\n : !isFragment && classRe.test(selector)\n ? context.getElementsByClassName(selector.slice(1).replace(/\\\\/g, ''))\n : !isFragment && tagRe.test(selector)\n ? context.getElementsByTagName(selector)\n : context.querySelectorAll(selector);\n}\n// @require ./find.ts\n// @require ./variables.ts\nclass Cash {\n constructor(selector, context) {\n if (!selector)\n return;\n if (isCash(selector))\n return selector;\n let eles = selector;\n if (isString(selector)) {\n const ctx = context || doc;\n eles = idRe.test(selector) && isDocument(ctx)\n ? ctx.getElementById(selector.slice(1).replace(/\\\\/g, ''))\n : htmlRe.test(selector)\n ? parseHTML(selector)\n : isCash(ctx)\n ? ctx.find(selector)\n : isString(ctx)\n ? cash(ctx).find(selector)\n : find(selector, ctx);\n if (!eles)\n return;\n }\n else if (isFunction(selector)) {\n return this.ready(selector); //FIXME: `fn.ready` is not included in `core`, but it's actually a core functionality\n }\n if (eles.nodeType || eles === win)\n eles = [eles];\n this.length = eles.length;\n for (let i = 0, l = this.length; i < l; i++) {\n this[i] = eles[i];\n }\n }\n init(selector, context) {\n return new Cash(selector, context);\n }\n}\nconst fn = Cash.prototype;\nconst cash = fn.init;\ncash.fn = cash.prototype = fn; // Ensuring that `cash () instanceof cash`\nfn.length = 0;\nfn.splice = splice; // Ensuring a cash collection gets printed as array-like in Chrome's devtools\nif (typeof Symbol === 'function') { // Ensuring a cash collection is iterable\n fn[Symbol['iterator']] = ArrayPrototype[Symbol['iterator']];\n}\nfunction isCash(value) {\n return value instanceof Cash;\n}\nfunction isWindow(value) {\n return !!value && value === value.window;\n}\nfunction isDocument(value) {\n return !!value && value.nodeType === 9;\n}\nfunction isDocumentFragment(value) {\n return !!value && value.nodeType === 11;\n}\nfunction isElement(value) {\n return !!value && value.nodeType === 1;\n}\nfunction isText(value) {\n return !!value && value.nodeType === 3;\n}\nfunction isBoolean(value) {\n return typeof value === 'boolean';\n}\nfunction isFunction(value) {\n return typeof value === 'function';\n}\nfunction isString(value) {\n return typeof value === 'string';\n}\nfunction isUndefined(value) {\n return value === undefined;\n}\nfunction isNull(value) {\n return value === null;\n}\nfunction isNumeric(value) {\n return !isNaN(parseFloat(value)) && isFinite(value);\n}\nfunction isPlainObject(value) {\n if (typeof value !== 'object' || value === null)\n return false;\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n}\ncash.isWindow = isWindow;\ncash.isFunction = isFunction;\ncash.isArray = isArray;\ncash.isNumeric = isNumeric;\ncash.isPlainObject = isPlainObject;\nfunction each(arr, callback, _reverse) {\n if (_reverse) {\n let i = arr.length;\n while (i--) {\n if (callback.call(arr[i], i, arr[i]) === false)\n return arr;\n }\n }\n else if (isPlainObject(arr)) {\n const keys = Object.keys(arr);\n for (let i = 0, l = keys.length; i < l; i++) {\n const key = keys[i];\n if (callback.call(arr[key], key, arr[key]) === false)\n return arr;\n }\n }\n else {\n for (let i = 0, l = arr.length; i < l; i++) {\n if (callback.call(arr[i], i, arr[i]) === false)\n return arr;\n }\n }\n return arr;\n}\ncash.each = each;\nfn.each = function (callback) {\n return each(this, callback);\n};\nfn.empty = function () {\n return this.each((i, ele) => {\n while (ele.firstChild) {\n ele.removeChild(ele.firstChild);\n }\n });\n};\nfunction extend(...sources) {\n const deep = isBoolean(sources[0]) ? sources.shift() : false;\n const target = sources.shift();\n const length = sources.length;\n if (!target)\n return {};\n if (!length)\n return extend(deep, cash, target);\n for (let i = 0; i < length; i++) {\n const source = sources[i];\n for (const key in source) {\n if (deep && (isArray(source[key]) || isPlainObject(source[key]))) {\n if (!target[key] || target[key].constructor !== source[key].constructor)\n target[key] = new source[key].constructor();\n extend(deep, target[key], source[key]);\n }\n else {\n target[key] = source[key];\n }\n }\n }\n return target;\n}\ncash.extend = extend;\nfn.extend = function (plugins) {\n return extend(fn, plugins);\n};\n// @require ./type_checking.ts\nconst splitValuesRe = /\\S+/g;\nfunction getSplitValues(str) {\n return isString(str) ? str.match(splitValuesRe) || [] : [];\n}\nfn.toggleClass = function (cls, force) {\n const classes = getSplitValues(cls);\n const isForce = !isUndefined(force);\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n each(classes, (i, c) => {\n if (isForce) {\n force ? ele.classList.add(c) : ele.classList.remove(c);\n }\n else {\n ele.classList.toggle(c);\n }\n });\n });\n};\nfn.addClass = function (cls) {\n return this.toggleClass(cls, true);\n};\nfn.removeAttr = function (attr) {\n const attrs = getSplitValues(attr);\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n each(attrs, (i, a) => {\n ele.removeAttribute(a);\n });\n });\n};\nfunction attr(attr, value) {\n if (!attr)\n return;\n if (isString(attr)) {\n if (arguments.length < 2) {\n if (!this[0] || !isElement(this[0]))\n return;\n const value = this[0].getAttribute(attr);\n return isNull(value) ? undefined : value;\n }\n if (isUndefined(value))\n return this;\n if (isNull(value))\n return this.removeAttr(attr);\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n ele.setAttribute(attr, value);\n });\n }\n for (const key in attr) {\n this.attr(key, attr[key]);\n }\n return this;\n}\nfn.attr = attr;\nfn.removeClass = function (cls) {\n if (arguments.length)\n return this.toggleClass(cls, false);\n return this.attr('class', '');\n};\nfn.hasClass = function (cls) {\n return !!cls && some.call(this, (ele) => isElement(ele) && ele.classList.contains(cls));\n};\nfn.get = function (index) {\n if (isUndefined(index))\n return slice.call(this);\n index = Number(index);\n return this[index < 0 ? index + this.length : index];\n};\nfn.eq = function (index) {\n return cash(this.get(index));\n};\nfn.first = function () {\n return this.eq(0);\n};\nfn.last = function () {\n return this.eq(-1);\n};\nfunction text(text) {\n if (isUndefined(text)) {\n return this.get().map(ele => isElement(ele) || isText(ele) ? ele.textContent : '').join('');\n }\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n ele.textContent = text;\n });\n}\nfn.text = text;\n// @require core/type_checking.ts\n// @require core/variables.ts\nfunction computeStyle(ele, prop, isVariable) {\n if (!isElement(ele))\n return;\n const style = win.getComputedStyle(ele, null);\n return isVariable ? style.getPropertyValue(prop) || undefined : style[prop] || ele.style[prop];\n}\n// @require ./compute_style.ts\nfunction computeStyleInt(ele, prop) {\n return parseInt(computeStyle(ele, prop), 10) || 0;\n}\n// @require css/helpers/compute_style_int.ts\nfunction getExtraSpace(ele, xAxis) {\n return computeStyleInt(ele, `border${xAxis ? 'Left' : 'Top'}Width`) + computeStyleInt(ele, `padding${xAxis ? 'Left' : 'Top'}`) + computeStyleInt(ele, `padding${xAxis ? 'Right' : 'Bottom'}`) + computeStyleInt(ele, `border${xAxis ? 'Right' : 'Bottom'}Width`);\n}\n// @require css/helpers/compute_style.ts\nconst defaultDisplay = {};\nfunction getDefaultDisplay(tagName) {\n if (defaultDisplay[tagName])\n return defaultDisplay[tagName];\n const ele = createElement(tagName);\n doc.body.insertBefore(ele, null);\n const display = computeStyle(ele, 'display');\n doc.body.removeChild(ele);\n return defaultDisplay[tagName] = display !== 'none' ? display : 'block';\n}\n// @require css/helpers/compute_style.ts\nfunction isHidden(ele) {\n return computeStyle(ele, 'display') === 'none';\n}\n// @require ./cash.ts\nfunction matches(ele, selector) {\n const matches = ele && (ele['matches'] || ele['webkitMatchesSelector'] || ele['msMatchesSelector']);\n return !!matches && !!selector && matches.call(ele, selector);\n}\n// @require ./matches.ts\n// @require ./type_checking.ts\nfunction getCompareFunction(comparator) {\n return isString(comparator)\n ? (i, ele) => matches(ele, comparator)\n : isFunction(comparator)\n ? comparator\n : isCash(comparator)\n ? (i, ele) => comparator.is(ele)\n : !comparator\n ? () => false\n : (i, ele) => ele === comparator;\n}\nfn.filter = function (comparator) {\n const compare = getCompareFunction(comparator);\n return cash(filter.call(this, (ele, i) => compare.call(ele, i, ele)));\n};\n// @require collection/filter.ts\nfunction filtered(collection, comparator) {\n return !comparator ? collection : collection.filter(comparator);\n}\nfn.detach = function (comparator) {\n filtered(this, comparator).each((i, ele) => {\n if (ele.parentNode) {\n ele.parentNode.removeChild(ele);\n }\n });\n return this;\n};\nconst fragmentRe = /^\\s*<(\\w+)[^>]*>/;\nconst singleTagRe = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/;\nconst containers = {\n '*': div,\n tr: tbody,\n td: tr,\n th: tr,\n thead: table,\n tbody: table,\n tfoot: table\n};\n//TODO: Create elements inside a document fragment, in order to prevent inline event handlers from firing\n//TODO: Ensure the created elements have the fragment as their parent instead of null, this also ensures we can deal with detatched nodes more reliably\nfunction parseHTML(html) {\n if (!isString(html))\n return [];\n if (singleTagRe.test(html))\n return [createElement(RegExp.$1)];\n const fragment = fragmentRe.test(html) && RegExp.$1;\n const container = containers[fragment] || containers['*'];\n container.innerHTML = html;\n return cash(container.childNodes).detach().get();\n}\ncash.parseHTML = parseHTML;\nfn.has = function (selector) {\n const comparator = isString(selector)\n ? (i, ele) => find(selector, ele).length\n : (i, ele) => ele.contains(selector);\n return this.filter(comparator);\n};\nfn.not = function (comparator) {\n const compare = getCompareFunction(comparator);\n return this.filter((i, ele) => (!isString(comparator) || isElement(ele)) && !compare.call(ele, i, ele));\n};\nfunction pluck(arr, prop, deep, until) {\n const plucked = [];\n const isCallback = isFunction(prop);\n const compare = until && getCompareFunction(until);\n for (let i = 0, l = arr.length; i < l; i++) {\n if (isCallback) {\n const val = prop(arr[i]);\n if (val.length)\n push.apply(plucked, val);\n }\n else {\n let val = arr[i][prop];\n while (val != null) {\n if (until && compare(-1, val))\n break;\n plucked.push(val);\n val = deep ? val[prop] : null;\n }\n }\n }\n return plucked;\n}\n// @require core/pluck.ts\n// @require core/variables.ts\nfunction getValue(ele) {\n if (ele.multiple && ele.options)\n return pluck(filter.call(ele.options, option => option.selected && !option.disabled && !option.parentNode.disabled), 'value');\n return ele.value || '';\n}\nfunction val(value) {\n if (!arguments.length)\n return this[0] && getValue(this[0]);\n return this.each((i, ele) => {\n const isSelect = ele.multiple && ele.options;\n if (isSelect || checkableRe.test(ele.type)) {\n const eleValue = isArray(value) ? map.call(value, String) : (isNull(value) ? [] : [String(value)]);\n if (isSelect) {\n each(ele.options, (i, option) => {\n option.selected = eleValue.indexOf(option.value) >= 0;\n }, true);\n }\n else {\n ele.checked = eleValue.indexOf(ele.value) >= 0;\n }\n }\n else {\n ele.value = isUndefined(value) || isNull(value) ? '' : value;\n }\n });\n}\nfn.val = val;\nfn.is = function (comparator) {\n const compare = getCompareFunction(comparator);\n return some.call(this, (ele, i) => compare.call(ele, i, ele));\n};\ncash.guid = 1;\nfunction unique(arr) {\n return arr.length > 1 ? filter.call(arr, (item, index, self) => indexOf.call(self, item) === index) : arr;\n}\ncash.unique = unique;\nfn.add = function (selector, context) {\n return cash(unique(this.get().concat(cash(selector, context).get())));\n};\nfn.children = function (comparator) {\n return filtered(cash(unique(pluck(this, ele => ele.children))), comparator);\n};\nfn.parent = function (comparator) {\n return filtered(cash(unique(pluck(this, 'parentNode'))), comparator);\n};\nfn.index = function (selector) {\n const child = selector ? cash(selector)[0] : this[0];\n const collection = selector ? this : cash(child).parent().children();\n return indexOf.call(collection, child);\n};\nfn.closest = function (comparator) {\n const filtered = this.filter(comparator);\n if (filtered.length)\n return filtered;\n const $parent = this.parent();\n if (!$parent.length)\n return filtered;\n return $parent.closest(comparator);\n};\nfn.siblings = function (comparator) {\n return filtered(cash(unique(pluck(this, ele => cash(ele).parent().children().not(ele)))), comparator);\n};\nfn.find = function (selector) {\n return cash(unique(pluck(this, ele => find(selector, ele))));\n};\n// @require core/variables.ts\n// @require collection/filter.ts\n// @require traversal/find.ts\nconst HTMLCDATARe = /^\\s*\\s*$/g;\nconst scriptTypeRe = /^$|^module$|\\/(java|ecma)script/i;\nconst scriptAttributes = ['type', 'src', 'nonce', 'noModule'];\nfunction evalScripts(node, doc) {\n const collection = cash(node);\n collection.filter('script').add(collection.find('script')).each((i, ele) => {\n if (scriptTypeRe.test(ele.type) && docEle.contains(ele)) { // The script type is supported // The element is attached to the DOM // Using `documentElement` for broader browser support\n const script = createElement('script');\n script.text = ele.textContent.replace(HTMLCDATARe, '');\n each(scriptAttributes, (i, attr) => {\n if (ele[attr])\n script[attr] = ele[attr];\n });\n doc.head.insertBefore(script, null);\n doc.head.removeChild(script);\n }\n });\n}\n// @require ./eval_scripts.ts\nfunction insertElement(anchor, target, left, inside, evaluate) {\n if (inside) { // prepend/append\n anchor.insertBefore(target, left ? anchor.firstChild : null);\n }\n else { // before/after\n if (anchor.nodeName === 'HTML') {\n anchor.parentNode.replaceChild(target, anchor);\n }\n else {\n anchor.parentNode.insertBefore(target, left ? anchor : anchor.nextSibling);\n }\n }\n if (evaluate) {\n evalScripts(target, anchor.ownerDocument);\n }\n}\n// @require ./insert_element.ts\nfunction insertSelectors(selectors, anchors, inverse, left, inside, reverseLoop1, reverseLoop2, reverseLoop3) {\n each(selectors, (si, selector) => {\n each(cash(selector), (ti, target) => {\n each(cash(anchors), (ai, anchor) => {\n const anchorFinal = inverse ? target : anchor;\n const targetFinal = inverse ? anchor : target;\n const indexFinal = inverse ? ti : ai;\n insertElement(anchorFinal, !indexFinal ? targetFinal : targetFinal.cloneNode(true), left, inside, !indexFinal);\n }, reverseLoop3);\n }, reverseLoop2);\n }, reverseLoop1);\n return anchors;\n}\nfn.after = function () {\n return insertSelectors(arguments, this, false, false, false, true, true);\n};\nfn.append = function () {\n return insertSelectors(arguments, this, false, false, true);\n};\nfunction html(html) {\n if (!arguments.length)\n return this[0] && this[0].innerHTML;\n if (isUndefined(html))\n return this;\n const hasScript = /]/.test(html);\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n if (hasScript) {\n cash(ele).empty().append(html);\n }\n else {\n ele.innerHTML = html;\n }\n });\n}\nfn.html = html;\nfn.appendTo = function (selector) {\n return insertSelectors(arguments, this, true, false, true);\n};\nfn.wrapInner = function (selector) {\n return this.each((i, ele) => {\n const $ele = cash(ele);\n const contents = $ele.contents();\n contents.length ? contents.wrapAll(selector) : $ele.append(selector);\n });\n};\nfn.before = function () {\n return insertSelectors(arguments, this, false, true);\n};\nfn.wrapAll = function (selector) {\n let structure = cash(selector);\n let wrapper = structure[0];\n while (wrapper.children.length)\n wrapper = wrapper.firstElementChild;\n this.first().before(structure);\n return this.appendTo(wrapper);\n};\nfn.wrap = function (selector) {\n return this.each((i, ele) => {\n const wrapper = cash(selector)[0];\n cash(ele).wrapAll(!i ? wrapper : wrapper.cloneNode(true));\n });\n};\nfn.insertAfter = function (selector) {\n return insertSelectors(arguments, this, true, false, false, false, false, true);\n};\nfn.insertBefore = function (selector) {\n return insertSelectors(arguments, this, true, true);\n};\nfn.prepend = function () {\n return insertSelectors(arguments, this, false, true, true, true, true);\n};\nfn.prependTo = function (selector) {\n return insertSelectors(arguments, this, true, true, true, false, false, true);\n};\nfn.contents = function () {\n return cash(unique(pluck(this, ele => ele.tagName === 'IFRAME' ? [ele.contentDocument] : (ele.tagName === 'TEMPLATE' ? ele.content.childNodes : ele.childNodes))));\n};\nfn.next = function (comparator, _all, _until) {\n return filtered(cash(unique(pluck(this, 'nextElementSibling', _all, _until))), comparator);\n};\nfn.nextAll = function (comparator) {\n return this.next(comparator, true);\n};\nfn.nextUntil = function (until, comparator) {\n return this.next(comparator, true, until);\n};\nfn.parents = function (comparator, _until) {\n return filtered(cash(unique(pluck(this, 'parentElement', true, _until))), comparator);\n};\nfn.parentsUntil = function (until, comparator) {\n return this.parents(comparator, until);\n};\nfn.prev = function (comparator, _all, _until) {\n return filtered(cash(unique(pluck(this, 'previousElementSibling', _all, _until))), comparator);\n};\nfn.prevAll = function (comparator) {\n return this.prev(comparator, true);\n};\nfn.prevUntil = function (until, comparator) {\n return this.prev(comparator, true, until);\n};\nfn.map = function (callback) {\n return cash(concat.apply([], map.call(this, (ele, i) => callback.call(ele, i, ele))));\n};\nfn.clone = function () {\n return this.map((i, ele) => ele.cloneNode(true));\n};\nfn.offsetParent = function () {\n return this.map((i, ele) => {\n let offsetParent = ele.offsetParent;\n while (offsetParent && computeStyle(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docEle;\n });\n};\nfn.slice = function (start, end) {\n return cash(slice.call(this, start, end));\n};\n// @require ./cash.ts\nconst dashAlphaRe = /-([a-z])/g;\nfunction camelCase(str) {\n return str.replace(dashAlphaRe, (match, letter) => letter.toUpperCase());\n}\nfn.ready = function (callback) {\n const cb = () => setTimeout(callback, 0, cash);\n if (doc.readyState !== 'loading') {\n cb();\n }\n else {\n doc.addEventListener('DOMContentLoaded', cb);\n }\n return this;\n};\nfn.unwrap = function () {\n this.parent().each((i, ele) => {\n if (ele.tagName === 'BODY')\n return;\n const $ele = cash(ele);\n $ele.replaceWith($ele.children());\n });\n return this;\n};\nfn.offset = function () {\n const ele = this[0];\n if (!ele)\n return;\n const rect = ele.getBoundingClientRect();\n return {\n top: rect.top + win.pageYOffset,\n left: rect.left + win.pageXOffset\n };\n};\nfn.position = function () {\n const ele = this[0];\n if (!ele)\n return;\n const isFixed = (computeStyle(ele, 'position') === 'fixed');\n const offset = isFixed ? ele.getBoundingClientRect() : this.offset();\n if (!isFixed) {\n const doc = ele.ownerDocument;\n let offsetParent = ele.offsetParent || doc.documentElement;\n while ((offsetParent === doc.body || offsetParent === doc.documentElement) && computeStyle(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.parentNode;\n }\n if (offsetParent !== ele && isElement(offsetParent)) {\n const parentOffset = cash(offsetParent).offset();\n offset.top -= parentOffset.top + computeStyleInt(offsetParent, 'borderTopWidth');\n offset.left -= parentOffset.left + computeStyleInt(offsetParent, 'borderLeftWidth');\n }\n }\n return {\n top: offset.top - computeStyleInt(ele, 'marginTop'),\n left: offset.left - computeStyleInt(ele, 'marginLeft')\n };\n};\nconst propMap = {\n /* GENERAL */\n class: 'className',\n contenteditable: 'contentEditable',\n /* LABEL */\n for: 'htmlFor',\n /* INPUT */\n readonly: 'readOnly',\n maxlength: 'maxLength',\n tabindex: 'tabIndex',\n /* TABLE */\n colspan: 'colSpan',\n rowspan: 'rowSpan',\n /* IMAGE */\n usemap: 'useMap'\n};\nfn.prop = function (prop, value) {\n if (!prop)\n return;\n if (isString(prop)) {\n prop = propMap[prop] || prop;\n if (arguments.length < 2)\n return this[0] && this[0][prop];\n return this.each((i, ele) => { ele[prop] = value; });\n }\n for (const key in prop) {\n this.prop(key, prop[key]);\n }\n return this;\n};\nfn.removeProp = function (prop) {\n return this.each((i, ele) => { delete ele[propMap[prop] || prop]; });\n};\nconst cssVariableRe = /^--/;\n// @require ./variables.ts\nfunction isCSSVariable(prop) {\n return cssVariableRe.test(prop);\n}\n// @require core/camel_case.ts\n// @require core/cash.ts\n// @require core/each.ts\n// @require core/variables.ts\n// @require ./is_css_variable.ts\nconst prefixedProps = {};\nconst { style } = div;\nconst vendorsPrefixes = ['webkit', 'moz', 'ms'];\nfunction getPrefixedProp(prop, isVariable = isCSSVariable(prop)) {\n if (isVariable)\n return prop;\n if (!prefixedProps[prop]) {\n const propCC = camelCase(prop);\n const propUC = `${propCC[0].toUpperCase()}${propCC.slice(1)}`;\n const props = (`${propCC} ${vendorsPrefixes.join(`${propUC} `)}${propUC}`).split(' ');\n each(props, (i, p) => {\n if (p in style) {\n prefixedProps[prop] = p;\n return false;\n }\n });\n }\n return prefixedProps[prop];\n}\n// @require core/type_checking.ts\n// @require ./is_css_variable.ts\nconst numericProps = {\n animationIterationCount: true,\n columnCount: true,\n flexGrow: true,\n flexShrink: true,\n fontWeight: true,\n gridArea: true,\n gridColumn: true,\n gridColumnEnd: true,\n gridColumnStart: true,\n gridRow: true,\n gridRowEnd: true,\n gridRowStart: true,\n lineHeight: true,\n opacity: true,\n order: true,\n orphans: true,\n widows: true,\n zIndex: true\n};\nfunction getSuffixedValue(prop, value, isVariable = isCSSVariable(prop)) {\n return !isVariable && !numericProps[prop] && isNumeric(value) ? `${value}px` : value;\n}\nfunction css(prop, value) {\n if (isString(prop)) {\n const isVariable = isCSSVariable(prop);\n prop = getPrefixedProp(prop, isVariable);\n if (arguments.length < 2)\n return this[0] && computeStyle(this[0], prop, isVariable);\n if (!prop)\n return this;\n value = getSuffixedValue(prop, value, isVariable);\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n if (isVariable) {\n ele.style.setProperty(prop, value);\n }\n else {\n ele.style[prop] = value;\n }\n });\n }\n for (const key in prop) {\n this.css(key, prop[key]);\n }\n return this;\n}\n;\nfn.css = css;\nfunction attempt(fn, arg) {\n try {\n return fn(arg);\n }\n catch (_a) {\n return arg;\n }\n}\n// @require core/attempt.ts\n// @require core/camel_case.ts\nconst JSONStringRe = /^\\s+|\\s+$/;\nfunction getData(ele, key) {\n const value = ele.dataset[key] || ele.dataset[camelCase(key)];\n if (JSONStringRe.test(value))\n return value;\n return attempt(JSON.parse, value);\n}\n// @require core/attempt.ts\n// @require core/camel_case.ts\nfunction setData(ele, key, value) {\n value = attempt(JSON.stringify, value);\n ele.dataset[camelCase(key)] = value;\n}\nfunction data(name, value) {\n if (!name) {\n if (!this[0])\n return;\n const datas = {};\n for (const key in this[0].dataset) {\n datas[key] = getData(this[0], key);\n }\n return datas;\n }\n if (isString(name)) {\n if (arguments.length < 2)\n return this[0] && getData(this[0], name);\n if (isUndefined(value))\n return this;\n return this.each((i, ele) => { setData(ele, name, value); });\n }\n for (const key in name) {\n this.data(key, name[key]);\n }\n return this;\n}\nfn.data = data;\nfunction getDocumentDimension(doc, dimension) {\n const docEle = doc.documentElement;\n return Math.max(doc.body[`scroll${dimension}`], docEle[`scroll${dimension}`], doc.body[`offset${dimension}`], docEle[`offset${dimension}`], docEle[`client${dimension}`]);\n}\neach([true, false], (i, outer) => {\n each(['Width', 'Height'], (i, prop) => {\n const name = `${outer ? 'outer' : 'inner'}${prop}`;\n fn[name] = function (includeMargins) {\n if (!this[0])\n return;\n if (isWindow(this[0]))\n return outer ? this[0][`inner${prop}`] : this[0].document.documentElement[`client${prop}`];\n if (isDocument(this[0]))\n return getDocumentDimension(this[0], prop);\n return this[0][`${outer ? 'offset' : 'client'}${prop}`] + (includeMargins && outer ? computeStyleInt(this[0], `margin${i ? 'Top' : 'Left'}`) + computeStyleInt(this[0], `margin${i ? 'Bottom' : 'Right'}`) : 0);\n };\n });\n});\neach(['Width', 'Height'], (index, prop) => {\n const propLC = prop.toLowerCase();\n fn[propLC] = function (value) {\n if (!this[0])\n return isUndefined(value) ? undefined : this;\n if (!arguments.length) {\n if (isWindow(this[0]))\n return this[0].document.documentElement[`client${prop}`];\n if (isDocument(this[0]))\n return getDocumentDimension(this[0], prop);\n return this[0].getBoundingClientRect()[propLC] - getExtraSpace(this[0], !index);\n }\n const valueNumber = parseInt(value, 10);\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n const boxSizing = computeStyle(ele, 'boxSizing');\n ele.style[propLC] = getSuffixedValue(propLC, valueNumber + (boxSizing === 'border-box' ? getExtraSpace(ele, !index) : 0));\n });\n };\n});\nconst displayProperty = '___cd';\nfn.toggle = function (force) {\n return this.each((i, ele) => {\n if (!isElement(ele))\n return;\n const hidden = isHidden(ele);\n const show = isUndefined(force) ? hidden : force;\n if (show) {\n ele.style.display = ele[displayProperty] || '';\n if (isHidden(ele)) {\n ele.style.display = getDefaultDisplay(ele.tagName);\n }\n }\n else if (!hidden) {\n ele[displayProperty] = computeStyle(ele, 'display');\n ele.style.display = 'none';\n }\n });\n};\nfn.hide = function () {\n return this.toggle(false);\n};\nfn.show = function () {\n return this.toggle(true);\n};\nconst eventsNamespace = '___ce';\nconst eventsNamespacesSeparator = '.';\nconst eventsFocus = { focus: 'focusin', blur: 'focusout' };\nconst eventsHover = { mouseenter: 'mouseover', mouseleave: 'mouseout' };\nconst eventsMouseRe = /^(mouse|pointer|contextmenu|drag|drop|click|dblclick)/i;\n// @require ./variables.ts\nfunction getEventNameBubbling(name) {\n return eventsHover[name] || eventsFocus[name] || name;\n}\n// @require ./variables.ts\nfunction parseEventName(eventName) {\n const parts = eventName.split(eventsNamespacesSeparator);\n return [parts[0], parts.slice(1).sort()]; // [name, namespace[]]\n}\nfn.trigger = function (event, data) {\n if (isString(event)) {\n const [nameOriginal, namespaces] = parseEventName(event);\n const name = getEventNameBubbling(nameOriginal);\n if (!name)\n return this;\n const type = eventsMouseRe.test(name) ? 'MouseEvents' : 'HTMLEvents';\n event = doc.createEvent(type);\n event.initEvent(name, true, true);\n event.namespace = namespaces.join(eventsNamespacesSeparator);\n event.___ot = nameOriginal;\n }\n event.___td = data;\n const isEventFocus = (event.___ot in eventsFocus);\n return this.each((i, ele) => {\n if (isEventFocus && isFunction(ele[event.___ot])) {\n ele[`___i${event.type}`] = true; // Ensuring the native event is ignored\n ele[event.___ot]();\n ele[`___i${event.type}`] = false; // Ensuring the custom event is not ignored\n }\n ele.dispatchEvent(event);\n });\n};\n// @require ./variables.ts\nfunction getEventsCache(ele) {\n return ele[eventsNamespace] = (ele[eventsNamespace] || {});\n}\n// @require core/guid.ts\n// @require events/helpers/get_events_cache.ts\nfunction addEvent(ele, name, namespaces, selector, callback) {\n const eventCache = getEventsCache(ele);\n eventCache[name] = (eventCache[name] || []);\n eventCache[name].push([namespaces, selector, callback]);\n ele.addEventListener(name, callback);\n}\nfunction hasNamespaces(ns1, ns2) {\n return !ns2 || !some.call(ns2, (ns) => ns1.indexOf(ns) < 0);\n}\n// @require ./get_events_cache.ts\n// @require ./has_namespaces.ts\n// @require ./parse_event_name.ts\nfunction removeEvent(ele, name, namespaces, selector, callback) {\n const cache = getEventsCache(ele);\n if (!name) {\n for (name in cache) {\n removeEvent(ele, name, namespaces, selector, callback);\n }\n }\n else if (cache[name]) {\n cache[name] = cache[name].filter(([ns, sel, cb]) => {\n if ((callback && cb.guid !== callback.guid) || !hasNamespaces(ns, namespaces) || (selector && selector !== sel))\n return true;\n ele.removeEventListener(name, cb);\n });\n }\n}\nfn.off = function (eventFullName, selector, callback) {\n if (isUndefined(eventFullName)) {\n this.each((i, ele) => {\n if (!isElement(ele) && !isDocument(ele) && !isWindow(ele))\n return;\n removeEvent(ele);\n });\n }\n else if (!isString(eventFullName)) {\n for (const key in eventFullName) {\n this.off(key, eventFullName[key]);\n }\n }\n else {\n if (isFunction(selector)) {\n callback = selector;\n selector = '';\n }\n each(getSplitValues(eventFullName), (i, eventFullName) => {\n const [nameOriginal, namespaces] = parseEventName(eventFullName);\n const name = getEventNameBubbling(nameOriginal);\n this.each((i, ele) => {\n if (!isElement(ele) && !isDocument(ele) && !isWindow(ele))\n return;\n removeEvent(ele, name, namespaces, selector, callback);\n });\n });\n }\n return this;\n};\nfn.remove = function (comparator) {\n filtered(this, comparator).detach().off();\n return this;\n};\nfn.replaceWith = function (selector) {\n return this.before(selector).remove();\n};\nfn.replaceAll = function (selector) {\n cash(selector).replaceWith(this);\n return this;\n};\nfunction on(eventFullName, selector, data, callback, _one) {\n if (!isString(eventFullName)) {\n for (const key in eventFullName) {\n this.on(key, selector, data, eventFullName[key], _one);\n }\n return this;\n }\n if (!isString(selector)) {\n if (isUndefined(selector) || isNull(selector)) {\n selector = '';\n }\n else if (isUndefined(data)) {\n data = selector;\n selector = '';\n }\n else {\n callback = data;\n data = selector;\n selector = '';\n }\n }\n if (!isFunction(callback)) {\n callback = data;\n data = undefined;\n }\n if (!callback)\n return this;\n each(getSplitValues(eventFullName), (i, eventFullName) => {\n const [nameOriginal, namespaces] = parseEventName(eventFullName);\n const name = getEventNameBubbling(nameOriginal);\n const isEventHover = (nameOriginal in eventsHover);\n const isEventFocus = (nameOriginal in eventsFocus);\n if (!name)\n return;\n this.each((i, ele) => {\n if (!isElement(ele) && !isDocument(ele) && !isWindow(ele))\n return;\n const finalCallback = function (event) {\n if (event.target[`___i${event.type}`])\n return event.stopImmediatePropagation(); // Ignoring native event in favor of the upcoming custom one\n if (event.namespace && !hasNamespaces(namespaces, event.namespace.split(eventsNamespacesSeparator)))\n return;\n if (!selector && ((isEventFocus && (event.target !== ele || event.___ot === name)) || (isEventHover && event.relatedTarget && ele.contains(event.relatedTarget))))\n return;\n let thisArg = ele;\n if (selector) {\n let target = event.target;\n while (!matches(target, selector)) {\n if (target === ele)\n return;\n target = target.parentNode;\n if (!target)\n return;\n }\n thisArg = target;\n }\n Object.defineProperty(event, 'currentTarget', {\n configurable: true,\n get() {\n return thisArg;\n }\n });\n Object.defineProperty(event, 'delegateTarget', {\n configurable: true,\n get() {\n return ele;\n }\n });\n Object.defineProperty(event, 'data', {\n configurable: true,\n get() {\n return data;\n }\n });\n const returnValue = callback.call(thisArg, event, event.___td);\n if (_one) {\n removeEvent(ele, name, namespaces, selector, finalCallback);\n }\n if (returnValue === false) {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n finalCallback.guid = callback.guid = (callback.guid || cash.guid++);\n addEvent(ele, name, namespaces, selector, finalCallback);\n });\n });\n return this;\n}\nfn.on = on;\nfunction one(eventFullName, selector, data, callback) {\n return this.on(eventFullName, selector, data, callback, true);\n}\n;\nfn.one = one;\nconst queryEncodeCRLFRe = /\\r?\\n/g;\nfunction queryEncode(prop, value) {\n return `&${encodeURIComponent(prop)}=${encodeURIComponent(value.replace(queryEncodeCRLFRe, '\\r\\n'))}`;\n}\nconst skippableRe = /file|reset|submit|button|image/i;\nconst checkableRe = /radio|checkbox/i;\nfn.serialize = function () {\n let query = '';\n this.each((i, ele) => {\n each(ele.elements || [ele], (i, ele) => {\n if (ele.disabled || !ele.name || ele.tagName === 'FIELDSET' || skippableRe.test(ele.type) || (checkableRe.test(ele.type) && !ele.checked))\n return;\n const value = getValue(ele);\n if (!isUndefined(value)) {\n const values = isArray(value) ? value : [value];\n each(values, (i, value) => {\n query += queryEncode(ele.name, value);\n });\n }\n });\n });\n return query.slice(1);\n};\n// @require core/types.ts\n// @require core/cash.ts\n// @require core/type_checking.ts\n// @require core/variables.ts\n// @require core/each.ts\n// @require core/extend.ts\n// @require core/find.ts\n// @require core/get_compare_function.ts\n// @require core/get_split_values.ts\n// @require core/guid.ts\n// @require core/parse_html.ts\n// @require core/unique.ts\n// @require attributes/add_class.ts\n// @require attributes/attr.ts\n// @require attributes/has_class.ts\n// @require attributes/prop.ts\n// @require attributes/remove_attr.ts\n// @require attributes/remove_class.ts\n// @require attributes/remove_prop.ts\n// @require attributes/toggle_class.ts\n// @require collection/add.ts\n// @require collection/each.ts\n// @require collection/eq.ts\n// @require collection/filter.ts\n// @require collection/first.ts\n// @require collection/get.ts\n// @require collection/index.ts\n// @require collection/last.ts\n// @require collection/map.ts\n// @require collection/slice.ts\n// @require css/css.ts\n// @require data/data.ts\n// @require dimensions/inner_outer.ts\n// @require dimensions/normal.ts\n// @require effects/hide.ts\n// @require effects/show.ts\n// @require effects/toggle.ts\n// @require events/off.ts\n// @require events/on.ts\n// @require events/one.ts\n// @require events/ready.ts\n// @require events/trigger.ts\n// @require forms/serialize.ts\n// @require forms/val.ts\n// @require manipulation/after.ts\n// @require manipulation/append.ts\n// @require manipulation/append_to.ts\n// @require manipulation/before.ts\n// @require manipulation/clone.ts\n// @require manipulation/detach.ts\n// @require manipulation/empty.ts\n// @require manipulation/html.ts\n// @require manipulation/insert_after.ts\n// @require manipulation/insert_before.ts\n// @require manipulation/prepend.ts\n// @require manipulation/prepend_to.ts\n// @require manipulation/remove.ts\n// @require manipulation/replace_all.ts\n// @require manipulation/replace_with.ts\n// @require manipulation/text.ts\n// @require manipulation/unwrap.ts\n// @require manipulation/wrap.ts\n// @require manipulation/wrap_all.ts\n// @require manipulation/wrap_inner.ts\n// @require offset/offset.ts\n// @require offset/offset_parent.ts\n// @require offset/position.ts\n// @require traversal/children.ts\n// @require traversal/closest.ts\n// @require traversal/contents.ts\n// @require traversal/find.ts\n// @require traversal/has.ts\n// @require traversal/is.ts\n// @require traversal/next.ts\n// @require traversal/next_all.ts\n// @require traversal/next_until.ts\n// @require traversal/not.ts\n// @require traversal/parent.ts\n// @require traversal/parents.ts\n// @require traversal/parents_until.ts\n// @require traversal/prev.ts\n// @require traversal/prev_all.ts\n// @require traversal/prev_until.ts\n// @require traversal/siblings.ts\n// @no-require extras/get_script.ts\n// @no-require extras/shorthands.ts\n// @require methods.ts\nexport default cash;\nexport { Cash };\n","import $ from 'cash-dom';\nexport type * from 'cash-dom';\n\ndeclare global {\n interface Window {\n $: typeof $\n }\n}\n\nwindow.$ = $;\n\nexport {$, $ as cash};\n","/**\n * Get all values in path from an object\n * @param object The object to access\n * @param pathName Access path\n * @returns All values in path\n * @example\n * const object = {\n * a: [{b: {c: 1}, d: 2}]\n * };\n *\n * deepGetPath('a[0].b.c'); // Output [[{b: {c: 1}, d: 2}], {b: {c: 1}, {c: 1}, 1]\n */\nexport function deepGetPath(object: object, pathName: string | string[]): (object | undefined)[] {\n if (object === null || object === undefined) {\n return [object, undefined];\n }\n\n if (typeof pathName === 'string') {\n pathName = pathName.split('.');\n }\n\n const fullPath = pathName.join('.');\n let context = object;\n const way = [context];\n while (typeof context === 'object' && context !== null && pathName.length) {\n let name = pathName.shift()!;\n let subName: string | undefined;\n const bracketIndex = name.indexOf('[');\n if (bracketIndex > 0 && bracketIndex < (name.length - 1) && name.endsWith(']')) {\n subName = name.substring(bracketIndex + 1, name.length - 1);\n name = name.substring(0, bracketIndex);\n }\n\n context = (context as Record)[name];\n way.push(context);\n if (subName !== undefined) {\n if (typeof context === 'object' && context !== null) {\n if (context instanceof Map) {\n context = context.get(subName);\n } else {\n context = (context as Record)[subName];\n }\n way.push(context);\n } else {\n throw new Error(`Cannot access property \"${name}[${subName}]\", the full path is \"${fullPath}\".`);\n }\n }\n }\n\n if (pathName.length) {\n throw new Error(`Cannot access property with rest path \"${pathName.join('.')}\", the full path is \"${fullPath}\".`);\n }\n\n return way;\n}\n\n/**\n * Get object inner value with dot-strings\n * @param object The object to access\n * @param pathName Access path\n * @param defaultValue Default value\n * @returns Final value\n * @example\n * const object = {\n * a: [{b: {c: 1}, d: 2}]\n * };\n *\n * deepGetPath('a[0].b.c'); // Output 1\n * deepGetPath('a[0].d'); // Output 2\n * deepGetPath('a'); // Output [{b: {c: 1}, d: 2}]\n */\nexport function deepGet(object: object, pathName: string | string[], defaultValue?: T): T | undefined {\n try {\n const way = deepGetPath(object, pathName);\n const lastValue = way[way.length - 1] as T | undefined;\n return lastValue === undefined ? defaultValue : lastValue;\n } catch (_) {\n return defaultValue;\n }\n}\n","\n/**\n * 格式化字符串\n * @param str 要格式化的字符串\n * @param args 格式化参数\n * @returns 格式化后的字符串\n * @example 通过参数序号格式化\n * const hello = formatString('{0} {1}!', 'Hello', 'world');\n * // hello 值为 'Hello world!'\n */\nexport function formatString(str: string, ...args: unknown[]): string;\n\n/**\n * 格式化字符串\n * @param str 要格式化的字符串\n * @param obj 格式化参数\n * @returns 格式化后的字符串\n * @example 通过对象名称格式化\n * const say = formatString('Say {what} to {who}', {what: 'hello', who: 'you'});\n * // say 值为 'Say hello to you'\n */\nexport function formatString(str: string, obj: Record): string;\n\nexport function formatString(str: string, ...args: [Record] | unknown[]): string {\n if (args.length === 0) {\n return str;\n }\n if (args.length === 1 && typeof args[0] === 'object' && args[0]) {\n const obj = args[0];\n Object.keys(obj).forEach(key => {\n const value = (obj as Record)[key] ?? '';\n str = str.replace(new RegExp(`\\\\{${key}\\\\}`, 'g'), `${value}`);\n });\n return str;\n }\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i] ?? '';\n str = str.replace(new RegExp(`\\\\{${i}\\\\}`, 'g'), `${arg}`);\n }\n return str;\n}\n\n/**\n * 字节单位表\n */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nenum BYTE_UNITS {\n B = 1,\n KB = 1024,\n MB = 1024 * 1024,\n GB = 1024 * 1024 * 1024,\n TB = 1024 * 1024 * 1024 * 1024,\n}\n\n/**\n * 格式化字节值为包含单位的字符串\n * @param size 字节大小\n * @param fixed 保留的小数点位数\n * @param unit 单位,如果留空,则自动使用最合适的单位\n * @returns 格式化后的字符串\n */\nexport function formatBytes(size: number, fixed = 2, unit?: keyof typeof BYTE_UNITS) {\n if (Number.isNaN(size)) {\n return '?KB';\n }\n if (!unit) {\n if (size < BYTE_UNITS.KB) {\n unit = 'B';\n } else if (size < BYTE_UNITS.MB) {\n unit = 'KB';\n } else if (size < BYTE_UNITS.GB) {\n unit = 'MB';\n } else if (size < BYTE_UNITS.TB) {\n unit = 'GB';\n } else {\n unit = 'TB';\n }\n }\n\n return (size / BYTE_UNITS[unit]).toFixed(fixed) + unit;\n}\n\n/**\n * 转换带单位的字节字符串为字节数\n * @param str 带单位的字节字符串\n * @returns 字节数\n */\nexport const convertBytes = (str: string) => {\n const pattern = /^[0-9]*(B|KB|MB|GB|TB)$/;\n str = str.toUpperCase();\n const matchRes = str.match(pattern);\n if (!matchRes) {\n return 0;\n }\n const unit = matchRes[1] as keyof typeof BYTE_UNITS;\n str = str.replace(unit, '');\n return Number.parseInt(str, 10) * BYTE_UNITS[unit];\n};\n","import {$} from '../cash';\nimport {deepGet} from '@zui/helpers/src/object/deep-get';\nimport {formatString} from '@zui/helpers/src/format-string';\nimport {I18nLangMap, I18nLangCode, I18nValuesMap} from './types';\n\nlet globalLangCode = (document.documentElement.getAttribute('lang') || 'zh_cn').toLowerCase().replace('-', '_');\n\nlet globalLangMap: I18nLangMap | undefined;\n\nexport function getLangCode() {\n return globalLangCode;\n}\n\nexport function setLangCode(langCode: I18nLangCode) {\n globalLangCode = langCode.toLowerCase();\n}\n\nexport function addI18nMap(map: I18nLangMap): void;\nexport function addI18nMap(code: I18nLangCode, values: I18nValuesMap): void;\nexport function addI18nMap(codeOrMap: I18nLangCode | I18nLangMap, values?: I18nValuesMap): void {\n if (!globalLangMap) {\n globalLangMap = {};\n }\n if (typeof codeOrMap === 'string') {\n codeOrMap = {[codeOrMap]: values ?? {}};\n }\n $.extend(true, globalLangMap, codeOrMap);\n}\n\nexport function i18n(maps: I18nLangMap | (I18nLangMap | undefined)[] | undefined, key: string, defaultValue?: T, langCode?: I18nLangCode, globalPrefix?: string): T | undefined;\nexport function i18n(maps: I18nLangMap | (I18nLangMap | undefined)[] | undefined, key: string, args?: string | (string | number)[] | Record, defaultValue?: T, langCode?: I18nLangCode, globalPrefix?: string): T | undefined;\nexport function i18n(maps: I18nLangMap | (I18nLangMap | undefined)[] | undefined, key: string, args?: string | (string | number)[] | Record, defaultValue?: T | I18nLangCode, langCode?: I18nLangCode, globalPrefix?: string): T | undefined {\n if (!Array.isArray(maps)) {\n maps = globalLangMap ? [globalLangMap, maps] : [maps];\n } else if (globalLangMap) {\n maps.unshift(globalLangMap);\n }\n if (typeof args === 'string') {\n globalPrefix = langCode;\n langCode = defaultValue as I18nLangCode;\n defaultValue = args;\n args = undefined;\n }\n const lang = langCode || globalLangCode;\n let value: T | undefined;\n for (const map of maps) {\n if (!map) {\n continue;\n }\n const mapValues = map[lang];\n if (!mapValues) {\n continue;\n }\n const mapKey = (globalPrefix && map === globalLangMap) ? `${globalPrefix}.${key}` : key;\n value = deepGet(mapValues, mapKey);\n if (value !== undefined) {\n break;\n }\n }\n if (value === undefined) {\n return defaultValue as T;\n }\n if (args) {\n return formatString(value as string, ...(Array.isArray(args) ? args : [args])) as T;\n }\n return value;\n}\n\nexport function getLang(key: string, args?: string | (string | number)[] | Record, defaultValue?: T, langCode?: I18nLangCode): T | undefined {\n return i18n(undefined, key, args, defaultValue, langCode);\n}\n\ni18n.addLang = addI18nMap;\ni18n.getLang = getLang;\ni18n.getCode = getLangCode;\ni18n.setCode = setLangCode;\n","import {addI18nMap} from './i18n';\n\naddI18nMap({\n 'zh_cn': {\n confirm: '确定',\n cancel: '取消',\n delete: '删除',\n add: '添加',\n },\n 'zh_tw': {\n confirm: '確定',\n cancel: '取消',\n delete: '刪除',\n add: '添加',\n },\n en: {\n confirm: 'Confirm',\n cancel: 'Cancel',\n delete: 'Delete',\n add: 'Add',\n },\n});\n","import {$} from '@zui/core';\n\nimport type {AjaxCallbackMap, AjaxCompleteCallback, AjaxErrorCallback, AjaxFormItemValue, AjaxSetting, AjaxSuccessCallback} from './types';\n\nfunction setHeader(headers: HeadersInit, name: string, value: string) {\n if (headers instanceof Headers) {\n headers.set(name, value);\n } else if (Array.isArray(headers)) {\n headers.push([name, value]);\n } else {\n headers[name] = value;\n }\n}\n\nfunction setFormItem(formData: FormData, name: string, value: AjaxFormItemValue | AjaxFormItemValue[]) {\n if (value === undefined || value === null) {\n return;\n }\n if (Array.isArray(value)) {\n value.forEach((v) => setFormItem(formData, name, v));\n } else {\n formData.append(name, value instanceof Blob ? value : String(value));\n }\n}\n\nfunction getDataType(contentType: string | undefined | null, accepts: Record | undefined) {\n if (contentType) {\n const map = {\n text: 'text/plain',\n html: 'text/html',\n json: 'application/json',\n ...accepts,\n };\n for (const [key, value] of Object.entries(map)) {\n if (value.split(',').map(x => x.trim()).includes(contentType)) {\n return key;\n }\n }\n }\n\n return 'text';\n}\n\nexport function createFormData(data: string | FormData | URLSearchParams | Record | [name: string, value: AjaxFormItemValue][], existingFormData?: FormData): FormData {\n const formData = existingFormData || new FormData();\n if (data) {\n if (typeof data === 'string') {\n data = new URLSearchParams(data);\n }\n if (data instanceof URLSearchParams) {\n data.forEach((value, name) => {\n setFormItem(formData, name, value);\n });\n } else if (Array.isArray(data)) {\n data.forEach(([name, value]) => {\n setFormItem(formData, name, value);\n });\n } else if (data instanceof FormData) {\n data.forEach((value, name) => {\n setFormItem(formData, name, value);\n });\n } else if ($.isPlainObject(data)) {\n Object.entries(data).forEach(([name, value]) => {\n setFormItem(formData, name, value);\n });\n }\n }\n return formData;\n}\n\nexport class Ajax {\n private declare _timeoutID: number;\n\n private _controller: AbortController;\n\n private _callbacks: {[P in keyof AjaxCallbackMap]: AjaxCallbackMap[P][];};\n\n private declare _abortError?: Error;\n\n setting: AjaxSetting;\n\n declare data: T;\n\n declare error: Error;\n\n declare response: Response;\n\n declare url: string;\n\n declare request: RequestInit;\n\n get completed() {\n return this.data !== undefined || this.error !== undefined;\n }\n\n get [Symbol.toStringTag]() {\n return 'Ajax';\n }\n\n constructor(setting: AjaxSetting) {\n this.setting = setting;\n this._controller = new AbortController();\n this._callbacks = {success: [], error: [], complete: []};\n }\n\n on(name: N, callback: AjaxCallbackMap[N]) {\n (this._callbacks[name]).push(callback);\n return this;\n }\n\n success(calback: AjaxSuccessCallback) {\n return this.on('success', calback);\n }\n\n done(calback: AjaxSuccessCallback) {\n return this.success(calback);\n }\n\n fail(calback: AjaxErrorCallback) {\n return this.on('error', calback);\n }\n\n complete(calback: AjaxCompleteCallback) {\n return this.on('complete', calback);\n }\n\n always(calback: AjaxCompleteCallback) {\n return this.complete(calback);\n }\n\n then(resolve: (data: T) => void, reject?: (error: Error) => void) {\n if (this.completed) {\n if (reject && this.error) {\n reject(this.error);\n } else {\n resolve(this.data);\n }\n } else {\n this.success((data) => resolve(data as T));\n if (reject) {\n this.fail(reject);\n }\n }\n return this;\n }\n\n catch(calback: (error: Error) => void) {\n if (this.error) {\n calback(this.error);\n return this;\n }\n return this.on('error', (error) => calback(error));\n }\n\n finally(onFinally: () => void) {\n if (this.completed) {\n onFinally();\n return this;\n }\n return this.complete(() => onFinally());\n }\n\n abort(abortError?: Error) {\n if (this.completed) {\n return false;\n }\n this._abortError = abortError;\n this._controller.abort();\n return true;\n }\n\n getResponseHeader(name: string) {\n return this.response?.headers.get(name);\n }\n\n private _init() {\n if (this.completed) {\n return;\n }\n const {\n url,\n type,\n data,\n processData = true,\n contentType,\n crossDomain,\n accepts,\n dataType,\n timeout,\n dataFilter,\n beforeSend,\n success,\n error,\n complete,\n ...initOptions\n } = this.setting;\n\n if (beforeSend?.(initOptions) === false) {\n return;\n }\n if (type) {\n initOptions.method = type;\n }\n let dataSetting = data;\n if (dataSetting) {\n if (processData) {\n dataSetting = createFormData(dataSetting);\n }\n initOptions.body = dataSetting as BodyInit;\n }\n if (crossDomain) {\n initOptions.mode = 'cors';\n }\n const headers = initOptions.headers || {};\n setHeader(headers, 'X-Requested-With', 'XMLHttpRequest');\n if (contentType) {\n setHeader(headers, 'Content-Type', contentType);\n }\n initOptions.headers = headers;\n\n if (initOptions.signal) {\n initOptions.signal.addEventListener('abort', () => {\n this.abort();\n });\n }\n if (success) {\n this.success(success);\n }\n if (error) {\n this.fail(error);\n }\n if (complete) {\n this.complete(complete);\n }\n initOptions.signal = this._controller.signal;\n this.url = url;\n this.request = initOptions;\n }\n\n private _emit(name: N, ...args: Parameters) {\n this._callbacks[name].forEach((callback) => {\n callback.call(this, ...(args as [arg0: Error & Response, statusText: string, arg2: string & Response]));\n });\n }\n\n async send(): Promise<[data?: D | undefined, error?: Error | undefined, response?: Response | undefined]> {\n if (this.completed) {\n return [];\n }\n this._init();\n\n const {timeout, dataType: dataTypeSetting, accepts, dataFilter, throws} = this.setting;\n if (timeout) {\n this._timeoutID = window.setTimeout(() => {\n this.abort(new Error('timeout'));\n }, timeout);\n }\n\n let response: Response | undefined;\n let error: Error | undefined;\n let data: unknown | undefined;\n try {\n response = await fetch(this.url, this.request);\n this.response = response;\n const {statusText} = response;\n if (response.ok) {\n const isAttachment = response.headers.get('Content-Disposition')?.startsWith('attachment');\n const dataType = isAttachment ? 'blob' : (dataTypeSetting || getDataType(response.headers.get('Content-Type'), accepts));\n if (isAttachment || dataType === 'blob' || dataType === 'file') {\n data = await response.blob();\n } else if (dataType === 'json') {\n data = await response.json();\n } else {\n data = await response.text();\n }\n this.data = data as T;\n const filteredData = dataFilter?.(data, dataType) ?? data;\n this._emit('success', filteredData, statusText, response);\n } else {\n throw new Error(statusText);\n }\n } catch (err) {\n error = err as Error;\n let skipTriggerError = false;\n if (error.name === 'AbortError') {\n if (this._abortError) {\n error = this._abortError;\n } else {\n skipTriggerError = true;\n }\n }\n this.error = error;\n if (!skipTriggerError) {\n this._emit('error', error, response?.statusText, error.message);\n }\n }\n\n if (this._timeoutID) {\n clearTimeout(this._timeoutID);\n }\n\n this._emit('complete', response, response?.statusText);\n if (error && throws) {\n throw error;\n }\n return [data as D, error, response];\n }\n}\n","import {$, Cash} from '@zui/core';\nimport {Ajax} from './ajax';\nimport type {AjaxFormData, AjaxSetting, AjaxSuccessCallback} from './types';\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n ajax(urlOrSetting: string | AjaxSetting, setting?: Partial): Ajax;\n\n getJSON(url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, success?: AjaxSuccessCallback): Ajax;\n\n get(url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, successOrDataType?: AjaxSuccessCallback | string, dataType?: string, method?: string): Ajax;\n\n post(url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, successOrDataType?: AjaxSuccessCallback | string, dataType?: string): Ajax;\n }\n\n interface Cash {\n load(this: Cash, url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, success?: AjaxSuccessCallback): Cash;\n }\n}\n\n/* Extend as $.ajax() to create ajax for cash. */\n$.ajax = (urlOrSetting: string | AjaxSetting, setting?: Partial) => {\n setting = setting || {};\n if (typeof urlOrSetting === 'string') {\n setting.url = urlOrSetting;\n } else {\n $.extend(setting, urlOrSetting);\n }\n const ajax = new Ajax(setting as AjaxSetting);\n ajax.send();\n return ajax;\n};\n\n/* Extend as $.getJSON() to create getJSON for cash. */\n$.getJSON = (url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, success?: AjaxSuccessCallback) => {\n if (typeof dataOrSuccess === 'function') {\n success = dataOrSuccess;\n dataOrSuccess = undefined;\n }\n return $.ajax({\n url,\n data: dataOrSuccess,\n success,\n dataType: 'json',\n });\n};\n\n/* Extend as $.get() to create get for cash. */\n$.get = (url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, successOrDataType?: AjaxSuccessCallback | string, dataType?: string, method = 'GET') => {\n let success: AjaxSuccessCallback | undefined;\n let data: AjaxFormData | undefined;\n if (typeof dataOrSuccess === 'function') {\n success = dataOrSuccess;\n data = undefined;\n } else {\n data = dataOrSuccess;\n }\n if (typeof successOrDataType === 'function') {\n success = successOrDataType;\n dataType = undefined;\n } else {\n dataType = successOrDataType;\n }\n return $.ajax({\n method,\n url,\n data,\n success,\n dataType,\n });\n};\n\n/* Extend as $.post() to create post for cash. */\n$.post = (url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, successOrDataType?: AjaxSuccessCallback | string, dataType?: string) => {\n return $.get(url, dataOrSuccess, successOrDataType, dataType, 'POST');\n};\n\n/* Extend as $.load() to create load for cash. */\n$.fn.load = function (this: Cash, url: string, dataOrSuccess?: AjaxFormData | AjaxSuccessCallback, success?: AjaxSuccessCallback): Cash {\n if (typeof dataOrSuccess === 'function') {\n success = dataOrSuccess;\n dataOrSuccess = undefined;\n }\n const [realUrl, selector] = url.split(' ');\n $.get(realUrl, dataOrSuccess, (data, statusText, response) => {\n if (selector) {\n data = $(data as string).find(selector).html();\n }\n $(this).html(data as string);\n success?.call(this, data, statusText, response);\n }, 'html');\n return this;\n};\n","import {$} from '../cash';\nimport {Ajax} from './ajax';\nimport type {AjaxSetting, FetcherSetting} from './types';\n\nexport async function fetchData(setting: FetcherSetting, args: A = ([] as unknown as A), extraAjaxSetting?: Partial | ((ajaxSetting: AjaxSetting) => Partial)): Promise {\n const ajaxSetting = {throws: true, dataType: 'json'} as AjaxSetting;\n if (typeof setting === 'string') {\n ajaxSetting.url = setting;\n } else if (typeof setting === 'object') {\n $.extend(ajaxSetting, setting);\n } else if (typeof setting === 'function') {\n const result = setting(...args);\n if (result instanceof Promise) {\n const data = await result;\n return data;\n }\n return result;\n }\n if (extraAjaxSetting) {\n $.extend(ajaxSetting, typeof extraAjaxSetting === 'function' ? extraAjaxSetting(ajaxSetting) : extraAjaxSetting);\n }\n const ajax = new Ajax(ajaxSetting);\n const [data] = await ajax.send();\n return data as T;\n}\n\nexport function isFetchSetting(setting: FetcherSetting | unknown): setting is FetcherSetting {\n return !!(setting && (typeof setting === 'string' || (typeof setting === 'object' && (setting as AjaxSetting).url) || typeof setting === 'function'));\n}\n\ndeclare module 'cash-dom' {\n interface CashStatic {\n fetch(setting: FetcherSetting, args?: A, extraAjaxSetting?: Partial | ((ajaxSetting: AjaxSetting) => Partial)): Promise\n }\n}\n\n$.fetch = fetchData;\n","import {$} from '../cash';\n\nexport function nextGid() {\n return $.guid++;\n}\n","export function isDiff(value1: unknown, value2: unknown) {\n if (value1 === value2) {\n return false;\n }\n if (value1 && value2 && typeof value1 === 'object' && typeof value2 === 'object') {\n const isArray1 = Array.isArray(value1);\n const isArray2 = Array.isArray(value2);\n if (isArray1 !== isArray2) {\n return true;\n }\n if (isArray1 && isArray2) {\n if (value1.length !== value2.length) {\n return true;\n }\n for (let i = 0; i < value1.length; i++) {\n if (isDiff(value1[i], value2[i])) {\n return true;\n }\n }\n return true;\n }\n\n const keys1 = Object.keys(value1);\n const keys2 = Object.keys(value2);\n if (keys1.length !== keys2.length) {\n return true;\n }\n for (const key of keys1) {\n if (isDiff((value1 as Record)[key], (value2 as Record)[key])) {\n return true;\n }\n }\n return true;\n }\n return true;\n}\n","import {isDiff} from './is-diff';\n\n/**\n * A class representing a computed value that can be cached and recomputed when its dependencies change.\n * @template T The type of the computed value.\n * @template D The type of the dependencies array.\n */\nexport class Computed {\n /**\n * The dependencies of the computed value.\n */\n protected _dependencies: D | (() => D);\n\n /**\n * The function that computes the value.\n */\n protected _compute: () => T;\n\n /**\n * The cached value of the computed value.\n */\n protected _value?: T;\n\n /**\n * The last dependencies array used to compute the value.\n */\n protected _lastDependencies: D | undefined;\n\n /**\n * Creates a new Computed instance.\n * @param compute The function that computes the value.\n * @param dependencies The dependencies of the computed value.\n */\n constructor(compute: () => T, dependencies: D | (() => D)) {\n this._compute = compute;\n this._dependencies = dependencies;\n }\n\n /**\n * Gets the computed value.\n */\n get value(): T {\n return this.compute();\n }\n\n /**\n * Gets the cached value of the computed value.\n */\n get cache(): T {\n return this._lastDependencies ? this._value as T : this.compute();\n }\n\n /**\n * Forces the computed value to be recomputed.\n * @param dependencies The new dependencies to use for recomputing the value.\n * @returns The recomputed value.\n */\n forceCompute(dependencies?: D | (() => D)) {\n this._lastDependencies = undefined;\n return this.compute(dependencies);\n }\n\n /**\n * Computes the value of the computed value.\n * @param dependencies The dependencies to use for computing the value.\n * @returns The computed value.\n */\n compute(dependencies?: D | (() => D)): T {\n if (dependencies !== undefined) {\n this._dependencies = dependencies;\n }\n\n dependencies = this._dependencies;\n if (typeof dependencies === 'function') {\n dependencies = dependencies();\n }\n\n // Check if dependencies changed.\n const lastDependencies = this._lastDependencies;\n if (!lastDependencies || dependencies.some((dept, index) => {\n return isDiff(dept instanceof Computed ? dept.value : dept, lastDependencies[index]);\n })) {\n this._value = this._compute();\n this._lastDependencies = dependencies.map(x => x instanceof Computed ? x.cache : x) as D;\n }\n\n return this._value as T;\n }\n}\n","import {$, Cash} from '../cash';\n\n/**\n * Classname like.\n */\nexport type ClassNameLike = string | null | undefined | boolean | {[key: string]: unknown} | (() => ClassNameLike) | ClassNameLike[];\n\n/**\n * Classname setting.\n */\nexport type ClassNameSetting = [name: string, toggle: boolean];\n\n/**\n * Get class name setting list from arguments.\n *\n * @param args Classname like arguments.\n * @returns Classname setting list.\n */\nexport function getClassList(...args: ClassNameLike[]): ClassNameSetting[] {\n const settings: ClassNameSetting[] = [];\n\n /* Indexes map to keep classname's order. */\n const indexes = new Map();\n\n const setSetting = (name: string | [name: string, toggle?: unknown], toggle?: unknown) => {\n if (Array.isArray(name)) {\n toggle = name[1];\n name = name[0];\n }\n if (!name.length) {\n return;\n }\n const index = indexes.get(name);\n if (typeof index === 'number') {\n settings[index][1] = !!toggle;\n } else {\n indexes.set(name, settings.length);\n settings.push([name, !!toggle]);\n }\n };\n\n args.forEach((arg) => {\n if (typeof arg === 'function') {\n arg = arg();\n }\n\n if (Array.isArray(arg)) {\n getClassList(...arg).forEach(setSetting);\n } else if (arg && typeof arg === 'object') {\n Object.entries(arg).forEach(setSetting);\n } else if (typeof arg === 'string') {\n arg.split(' ').forEach(name => setSetting(name, true));\n }\n });\n\n return settings.sort((a, b) => (indexes.get(a[0]) || 0) - (indexes.get(b[0]) || 0));\n}\n\n/**\n * Get classname string from arguments.\n *\n * @param args Classname like arguments.\n * @returns Classname string.\n */\nexport const classes = (...args: ClassNameLike[]): string => {\n return getClassList(...args).reduce((classList, [name, toggle]) => {\n if (toggle) {\n classList.push(name);\n }\n return classList;\n }, []).join(' ');\n};\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n classes(...args: ClassNameLike[]): string;\n }\n\n interface Cash {\n setClass(merge: ClassNameLike | boolean, ...args: ClassNameLike[]): Cash;\n }\n}\n\n/* Extend as $.classes() */\n$.classes = classes;\n\n/* Extend as $.fn.setClass() */\n$.fn.setClass = function (this: Cash, merge: ClassNameLike | boolean, ...args: ClassNameLike[]): Cash {\n return this.each((_, ele) => {\n const $ele = $(ele);\n if (merge === true) {\n $ele.attr('class', classes($ele.attr('class'), ...args));\n } else {\n $ele.addClass(classes(merge, ...args));\n }\n });\n};\n","import {$, Cash} from '../cash';\n\n/**\n * Cache for data associated with the target object.\n */\nconst cache = new WeakMap>();\n\n/**\n * Store data associated with the target object with key value in the cache.\n *\n * @param target Target object to store data.\n * @param key Key to store.\n * @param value Value to store.\n */\nexport function storeData(target: object, key: string | null, value?: unknown): void;\n\n/**\n * Store data associated with the target object in the cache.\n *\n * @param target Target object to store data.\n * @param data Data to store.\n */\nexport function storeData(target: object, data: Record): void;\n\n/**\n * Store data associated with the target object in the cache.\n *\n * @param target Target object to store data.\n * @param keyOrData Key or data to store.\n * @param value Value to store.\n */\nexport function storeData(target: object, keyOrData: string | Record | null, value?: unknown): void {\n const hasCache = cache.has(target);\n const data = hasCache ? cache.get(target)! : {};\n if (typeof keyOrData === 'string') {\n data[keyOrData] = value;\n } else if (keyOrData === null) {\n Object.keys(data).forEach((key) => {\n delete data[key];\n });\n } else {\n Object.assign(data, keyOrData);\n }\n\n Object.keys(data).forEach((key) => {\n if (data[key] === undefined) {\n delete data[key];\n }\n });\n\n if (Object.keys(data).length) {\n if (!hasCache && target instanceof Element) {\n Object.assign(data, $(target).dataset(), data);\n }\n cache.set(target, data);\n } else {\n cache.delete(target);\n }\n}\n\n/**\n * Take data associated with the target object from the cache.\n *\n * @param target Target object to take data.\n */\nexport function takeData(target: object): Record;\n\n/**\n * Take data associated by key with the target object from the cache.\n *\n * @param target Target object to take data.\n * @param key Key to take.\n */\nexport function takeData(target: object, key: string): unknown;\n\n/**\n * Take data associated by key with the target object from the cache.\n *\n * @param target Target object to take data.\n * @param key Key to take.\n */\nexport function takeData(target: object, key: string | undefined, skipElementData: boolean): unknown;\n\n/**\n * Take data associated with the target object from the cache.\n *\n * @param target Target object to take data.\n * @param key Key to take.\n * @returns Data associated with the target object.\n */\nexport function takeData(target: object, key?: string, skipElementData?: boolean): unknown {\n let data = cache.get(target) || {};\n if (!skipElementData && target instanceof Element) {\n data = Object.assign({}, $(target).dataset(), data);\n }\n if (key === undefined) {\n return data;\n }\n return data[key];\n}\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n dataset(): Record | undefined;\n dataset(name: string): unknown | undefined;\n dataset(name: string, value: unknown): Cash;\n dataset(dataset: Record): Cash;\n\n removeData(name?: string): Cash;\n }\n}\n\n/* Backup the origin $.fn.data method. */\n$.fn.dataset = $.fn.data;\n\n/* Extend as $.fn.data() */\n$.fn.data = function (this: Cash, ...args: (string | Record | unknown)[]) {\n if (!this.length) {\n return;\n }\n const [data, value] = args;\n if (!args.length || (args.length === 1 && typeof data === 'string')) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return takeData(this[0]!, data as string) as any;\n }\n return this.each((_, ele) => {\n return storeData(ele, data as string, value);\n });\n};\n\n/* Extend as $.fn.removeData() */\n$.fn.removeData = function (this: Cash, name: string | null = null) {\n return this.each((_, ele) => {\n return storeData(ele, name);\n });\n};\n","import {$, Cash, Selector} from '../cash';\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n z(): Record | undefined;\n z(name: string): unknown | undefined;\n z(name: string, value: unknown): Cash;\n z(data: Record): Cash;\n }\n}\n\nexport function getZData(selector: Selector, prefix = 'z-'): Record | undefined {\n const element = $(selector)[0];\n if (!element) {\n return;\n }\n return Array.from(element.attributes).reduce>((data, attribute) => {\n let {name, value} = attribute;\n if (name.startsWith(prefix)) {\n name = name.slice(prefix.length).replace(/-([a-z])/g, (g) => g[1].toUpperCase());\n try {\n if (value.startsWith('RAWJS<') && value.endsWith('>RAWJS')) {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const func = new Function(`return ${value.substring(6, value.length - 6)}`);\n value = func();\n } else {\n value = JSON.parse(value);\n }\n } catch (error) {\n // Ignore.\n }\n data[name] = value;\n }\n return data;\n }, {});\n}\n\nexport function setZData(selector: Selector, data: Record, prefix = 'z-') {\n const $element = $(selector);\n Object.keys(data).forEach((name) => {\n let value = data[name];\n if (typeof value === 'function') {\n value = `RAWJS<${value}>RAWJS`;\n }\n if (typeof value !== 'string') {\n value = JSON.stringify(value);\n }\n name = name.replace(/[A-Z]/g, (g) => `-${g.toLowerCase()}`);\n $element.attr(`${prefix}${name}`, value as string);\n });\n}\n\nfunction z(): Record | undefined;\nfunction z(name: string): unknown | undefined;\nfunction z(name: string, value: unknown): Cash;\nfunction z(data: Record): Cash;\nfunction z(this: Cash, ...args: unknown[]): Record | unknown | Cash | undefined {\n const argsLength = args.length;\n if (!argsLength) {\n return getZData(this);\n }\n if (argsLength === 1) {\n const [nameOrData] = args;\n if (typeof nameOrData === 'string') {\n return getZData(this)?.[nameOrData];\n }\n if ($.isPlainObject(nameOrData)) {\n setZData(this, nameOrData);\n }\n return this;\n }\n setZData(this, {[args[0] as string]: args[1]});\n return this;\n}\n\n/* Extend as $.fn.z() */\n$.fn.z = z;\n","import {$, Cash} from '../cash';\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n _attr(): undefined;\n _attr(attrs: string): string | null;\n _attr(attrs: string, value: string): this;\n _attr(attrs: Record): this;\n\n attr(attrs: string, value: string | null): Cash;\n attr(attrs: Record): Cash;\n }\n}\n\n/* Backup the origin $.fn.attr() method. */\n$.fn._attr = $.fn.attr;\n\n/* Extend the attr method. */\n$.fn.extend({\n attr(this: Cash, ...args: (string | Record | null)[]): Cash | string | null | undefined {\n const [attrs, value] = args;\n if (!args.length || (args.length === 1 && typeof attrs === 'string')) {\n // eslint-disable-next-line prefer-spread\n return this._attr.apply(this, args as [attrs: Record]);\n }\n if (typeof attrs === 'object') {\n if (attrs) {\n Object.keys(attrs).forEach((key) => {\n const val = attrs[key];\n if (val === null) {\n this.removeAttr(key);\n } else {\n this._attr(key, val);\n }\n });\n }\n return this;\n }\n if (value === null) {\n return this.removeAttr(attrs as string);\n }\n return this._attr(attrs as string, value as string);\n },\n});\n","import {$} from '../cash';\n\n/**\n * Cash event.\n */\ntype CashEvent = Exclude[0], string>;\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n Event(event: string, data?: unknown): CashEvent;\n }\n}\n\n/* Extend as $.Event() to create custom event for cash. */\n$.Event = (event: string, data?: unknown): CashEvent => {\n const [name, ...namespaces] = event.split('.');\n const eventObject = new Event(name, {\n bubbles: true,\n cancelable: true,\n });\n (eventObject as Event & {namespace: string}).namespace = namespaces.join('.');\n (eventObject as Event & {___ot: string}).___ot = name;\n (eventObject as Event & {___td: unknown}).___td = data;\n return eventObject as unknown as CashEvent;\n};\n","export const delay = (ms: number, setTimerID?: (timerID: number) => void) => new Promise(resolve => {\n const id = window.setTimeout(resolve, ms);\n if (setTimerID) {\n setTimerID(id);\n }\n});\n","import {$} from '../cash';\n\nexport const shareData: Record = {};\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n share: Record;\n }\n}\n\n/** Define $.share helper. */\n$.share = shareData;\n","var n,l,u,t,i,o,r,f,e,c={},s=[],a=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,v=Array.isArray;function h(n,l){for(var u in l)n[u]=l[u];return n}function p(n){var l=n.parentNode;l&&l.removeChild(n)}function y(l,u,t){var i,o,r,f={};for(r in u)\"key\"==r?i=u[r]:\"ref\"==r?o=u[r]:f[r]=u[r];if(arguments.length>2&&(f.children=arguments.length>3?n.call(arguments,2):t),\"function\"==typeof l&&null!=l.defaultProps)for(r in l.defaultProps)void 0===f[r]&&(f[r]=l.defaultProps[r]);return d(l,f,i,o,null)}function d(n,t,i,o,r){var f={type:n,props:t,key:i,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null==r&&null!=l.vnode&&l.vnode(f),f}function _(){return{current:null}}function k(n){return n.children}function b(n,l){this.props=n,this.context=l}function g(n,l){if(null==l)return n.__?g(n.__,n.__.__k.indexOf(n)+1):null;for(var u;ll&&i.sort(f));x.__r=0}function P(n,l,u,t,i,o,r,f,e,a,h){var p,y,_,b,m,w,x,P,C,D=0,H=t&&t.__k||s,I=H.length,T=I,j=l.length;for(u.__k=[],p=0;p0?d(b.type,b.props,b.key,b.ref?b.ref:null,b.__v):b)?(b.__=u,b.__b=u.__b+1,-1===(P=A(b,H,x=p+D,T))?_=c:(_=H[P]||c,H[P]=void 0,T--),z(n,b,_,i,o,r,f,e,a,h),m=b.__e,(y=b.ref)&&_.ref!=y&&(_.ref&&N(_.ref,null,b),h.push(y,b.__c||m,b)),null!=m&&(null==w&&(w=m),(C=_===c||null===_.__v)?-1==P&&D--:P!==x&&(P===x+1?D++:P>x?T>j-x?D+=P-x:D--:D=P(null!=e?1:0))for(;r>=0||f=0){if((e=l[r])&&i==e.key&&o===e.type)return r;r--}if(f2&&(e.children=arguments.length>3?n.call(arguments,2):t),d(l.type,e,i||l.key,o||l.ref,null)}function G(n,l){var u={__c:l=\"__cC\"+e++,__:n,Consumer:function(n,l){return n.children(l)},Provider:function(n){var u,t;return this.getChildContext||(u=[],(t={})[l]=this,this.getChildContext=function(){return t},this.shouldComponentUpdate=function(n){this.props.value!==n.value&&u.some(function(n){n.__e=!0,w(n)})},this.sub=function(n){u.push(n);var l=n.componentWillUnmount;n.componentWillUnmount=function(){u.splice(u.indexOf(n),1),l&&l.call(n)}}),n.children}};return u.Provider.__=u.Consumer.contextType=u}n=s.slice,l={__e:function(n,l,u,t){for(var i,o,r;l=l.__;)if((i=l.__c)&&!i.__)try{if((o=i.constructor)&&null!=o.getDerivedStateFromError&&(i.setState(o.getDerivedStateFromError(n)),r=i.__d),null!=i.componentDidCatch&&(i.componentDidCatch(n,t||{}),r=i.__d),r)return i.__E=i}catch(l){n=l}throw n}},u=0,t=function(n){return null!=n&&void 0===n.constructor},b.prototype.setState=function(n,l){var u;u=null!=this.__s&&this.__s!==this.state?this.__s:this.__s=h({},this.state),\"function\"==typeof n&&(n=n(h({},u),this.props)),n&&h(u,n),null!=n&&this.__v&&(l&&this._sb.push(l),w(this))},b.prototype.forceUpdate=function(n){this.__v&&(this.__e=!0,n&&this.__h.push(n),w(this))},b.prototype.render=k,i=[],r=\"function\"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,f=function(n,l){return n.__v.__b-l.__v.__b},x.__r=0,e=0;export{b as Component,k as Fragment,F as cloneElement,G as createContext,y as createElement,_ as createRef,y as h,E as hydrate,t as isValidElement,l as options,B as render,C as toChildArray};\n//# sourceMappingURL=preact.module.js.map\n","import {ComponentChildren, toChildArray} from 'preact';\nimport {$} from '../cash';\n\nexport function mergeProps = Record>(props: Record, ...args: unknown[]) {\n args.forEach(arg => {\n if (!arg || typeof arg !== 'object') {\n return;\n }\n Object.keys(arg as Partial).forEach(key => {\n let value = (arg as Record)[key];\n const oldValue = props[key];\n if (value === oldValue) {\n return;\n }\n if (oldValue !== undefined) {\n if (key === 'className' || key.endsWith('Class')) {\n value = [oldValue, value];\n } else if (key === 'children') {\n value = [...toChildArray(oldValue), ...toChildArray(value as ComponentChildren)];\n } else if (typeof oldValue == 'object' && (key === 'style' || key.endsWith('Style') || key === 'attrs' || key.endsWith('Attrs') || key === 'props')) {\n value = $.extend(oldValue, value);\n }\n }\n props[key] = value;\n });\n });\n return props;\n}\n\nexport function removeUndefinedProps(props: Record) {\n Object.keys(props).forEach(key => {\n if (props[key] === undefined) {\n delete props[key];\n }\n });\n return props;\n}\n","import {$, Cash, Selector} from '../cash';\nimport {takeData} from './data';\nimport {getZData} from './z';\n\ntype ZUIComponentOptions = Record;\n\ndeclare class ZUIComponentClass {\n gid: number;\n constructor(element: HTMLElement, options: ZUIComponentOptions);\n setOptions(options: ZUIComponentOptions): void;\n render(options?: ZUIComponentOptions): void;\n destroy(): void;\n}\n\ninterface ZUIComponent {\n ZUI: string;\n NAME: string;\n MULTI_INSTANCE: boolean;\n defineFn(): void;\n get(selector?: Selector): ZUIComponentClass;\n getAll(selector?: Selector): ZUIComponentClass[];\n query(selector?: Selector, key?: string | number): ZUIComponentClass | undefined;\n new (element: HTMLElement, options: ZUIComponentOptions): ZUIComponentClass;\n}\n\nexport const componentsMap = new Map();\n\nexport function getComponent(name?: string): ZUIComponent | undefined {\n const {zui} = window as unknown as {zui: Record};\n if (!componentsMap.size || (name && !componentsMap.has(name.toUpperCase()))) {\n Object.keys(zui).forEach((n) => {\n const Component = zui[n];\n if (!Component.NAME || !Component.ZUI) {\n return;\n }\n componentsMap.set(n.toLowerCase(), Component);\n });\n }\n return name ? componentsMap.get(name.toLowerCase()) : undefined;\n}\n\nexport function create(name: string, element: HTMLElement, options: ZUIComponentOptions) {\n const Component = getComponent(name);\n if (!Component) {\n return null;\n }\n if (!Component.MULTI_INSTANCE && Component.get(element)) {\n console.error(`[ZUI] cannot create component \"${name}\" on element which already has a component instance.`, {element, options});\n return null;\n }\n return new Component(element, options);\n}\n\nexport function defineFn(name?: string) {\n if (name) {\n const Component = getComponent(name);\n if (Component) {\n Component.defineFn();\n }\n } else {\n getComponent();\n componentsMap.forEach((Component) => {\n Component.defineFn();\n });\n }\n}\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n zuiInit(this: Cash): Cash;\n zui(this: Cash, name?: string, key?: string | number | true): ZUIComponentClass | ZUIComponentClass[] | Record | undefined;\n }\n}\n\n/** Define the $.fn.zuiInit method. */\n$.fn.zuiInit = function (this: Cash) {\n this.find('[data-zui]').each(function () {\n const $element = $(this);\n let options = getZData($element, 'data-')!;\n const [name, optionsName] = (options.zui as string).split(':');\n if ($element.zui(name)) {\n return;\n }\n if (optionsName) {\n options = $.share[optionsName] as Record;\n } else {\n delete options.zui;\n }\n requestAnimationFrame(() => create(name, this, options));\n });\n this.find('.hide-before-init').removeClass('invisible hidden opacity-0');\n this.find('.scroll-into-view').scrollIntoView();\n return this;\n};\n\n/** Define the $.fn.zui method. */\n$.fn.zui = function (this: Cash, name?: string | true, key?: string | number | true) {\n const element = this[0];\n if (!element) {\n return;\n }\n if (typeof name !== 'string') {\n const data = takeData(element, undefined, true) as Record;\n const result: Record = {};\n let lastComponent: ZUIComponentClass | undefined;\n Object.keys(data).forEach((dataKey) => {\n if (dataKey.startsWith('zui.')) {\n const component = data[dataKey] as ZUIComponentClass;\n result[dataKey] = component;\n if (!lastComponent || lastComponent.gid < component.gid) {\n lastComponent = result[dataKey];\n }\n }\n });\n return name === true ? result : lastComponent;\n }\n const Component = getComponent(name);\n if (!Component) {\n return;\n }\n if (key === true) {\n return Component.getAll(element);\n }\n return Component.query(element, key);\n};\n\n/** Auto call creator on elements match [data-zui]. */\n$(() => {\n $('body').zuiInit();\n});\n","import {$, Cash, Selector} from '../cash';\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n disableScroll(disable?: boolean): Cash;\n enableScroll(enable?: boolean): Cash;\n }\n}\n\nexport function disableScroll(selector: Selector, disable = true): void {\n const $element = $(selector);\n const element = $element[0] as HTMLElement;\n const dataName = 'zui-disable-scroll';\n if (disable) {\n if ($element.data(dataName)) {\n return;\n }\n if (($element.css('scrollbar-gutter') || '').includes('stable')) {\n $element.data(dataName, {overflow: $element.css('overflow')}).css('overflow', 'hidden');\n return;\n }\n const scrollbarWidth = (element === document.body) ? (window.innerWidth - document.body.clientWidth) : (element.offsetWidth - element.clientWidth);\n if (!scrollbarWidth) {\n return;\n }\n const paddingRight = $element.css('paddingRight') || '0';\n $element.data(dataName, {\n paddingRight: paddingRight,\n overflow: $element.css('overflow'),\n }).css({\n paddingRight: `${scrollbarWidth + Number.parseInt(paddingRight, 10)}px`,\n overflow: 'hidden',\n });\n } else {\n const oldStyle = $element.data(dataName);\n if (!oldStyle) {\n return;\n }\n $element.css(oldStyle).removeData(dataName);\n }\n}\n\n/* Extend as $.fn.disableScroll() */\n$.fn.disableScroll = function (this: Cash, disable = true): Cash {\n return this.each((_, ele) => {\n disableScroll(ele, disable);\n });\n};\n\n$.fn.enableScroll = function (this: Cash, enable = true): Cash {\n return this.disableScroll(!enable);\n};\n","export type SizeSetting = number | `${number}%` | `${number}px` | `${number}/${number}` | (string & {});\n\nexport function parseSize(size: SizeSetting): [value: number, type?: 'px' | '%'] {\n if (typeof size === 'number') {\n return [size];\n }\n let match = size.match(/(\\d+)(%|px)?/);\n if (match) {\n return [parseInt(match[1]), match[2] as 'px' | '%'];\n }\n match = size.match(/(\\d+)\\/(\\d+)/);\n if (match) {\n return [100 * parseInt(match[1]) / parseInt(match[2]), '%'];\n }\n return [NaN];\n}\n\nexport function toCssSize(size: SizeSetting | undefined | null): string | null {\n if (size === undefined || size === null) {\n return null;\n }\n const [val, unit = 'px'] = parseSize(size);\n if (Number.isNaN(val)) {\n return typeof size === 'string' ? size : null;\n }\n return `${val}${unit}`;\n}\n","export async function downloadFile(file: Blob | Response | string, fileName?: string): Promise {\n if (file instanceof Blob) {\n const link = document.createElement('a');\n link.href = window.URL.createObjectURL(file);\n if (fileName) {\n link.download = fileName;\n }\n link.click();\n link.remove();\n return file;\n }\n if (file instanceof Response) {\n const blob = await file.blob();\n fileName = fileName || file.headers.get('Content-Disposition')?.split(';')[1]?.split('=')[1]?.replace(/\"/g, '');\n return downloadFile(blob, fileName);\n }\n const response = await fetch(file);\n return downloadFile(response);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {$, type Cash, type Selector} from '../cash';\n\ntype EventCallback = {\n (event: any, data?: any): any;\n guid?: number;\n};\n\nexport class Bus {\n protected _$target: Cash;\n\n constructor(target: Selector) {\n this._$target = $(target);\n }\n\n on(events: Record): this;\n on(events: Record, selector: string): this;\n on(events: Record, data: any): this;\n on(events: Record, selector: string | null | undefined, data: any): this;\n on(events: string, callback: EventCallback): this;\n on(events: string, selector: string, callback: EventCallback): this;\n on(events: string, data: any, callback: EventCallback): this;\n on(events: string, selector: string | null | undefined, data: any, callback: EventCallback, _one?: boolean): this;\n on(...args: any[]): this {\n this._$target.on(...(args as Parameters));\n return this;\n }\n\n one(events: Record): this;\n one(events: Record, selector: string): this;\n one(events: Record, data: any): this;\n one(events: Record, selector: string | null | undefined, data: any): this;\n one(events: string, callback: EventCallback): this;\n one(events: string, selector: string, callback: EventCallback): this;\n one(events: string, data: any, callback: EventCallback): this;\n one(events: string, selector: string | null | undefined, data: any, callback: EventCallback): this;\n one(...args: any[]): this {\n this._$target.one(...(args as Parameters));\n return this;\n }\n\n off(): this;\n off(events: string): this;\n off(events: Record): this;\n off(events: string, callback: EventCallback): this;\n off(events: string, selector: string, callback: EventCallback): this;\n off(...args: any[]): this {\n this._$target.off(...(args as Parameters));\n return this;\n }\n\n trigger(event: Event | string, data?: any): this;\n trigger(...args: any[]): this {\n this._$target.trigger(...(args as Parameters));\n return this;\n }\n}\n\nexport const bus = new Bus(document);\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n bus: Bus;\n\n on(events: Record): Bus;\n on(events: Record, selector: string): Bus;\n on(events: Record, data: any): Bus;\n on(events: Record, selector: string | null | undefined, data: any): Bus;\n on(events: string, callback: EventCallback): Bus;\n on(events: string, selector: string, callback: EventCallback): Bus;\n on(events: string, data: any, callback: EventCallback): Bus;\n on(events: string, selector: string | null | undefined, data: any, callback: EventCallback, _one?: boolean): Bus;\n\n one(events: Record): Bus;\n one(events: Record, selector: string): Bus;\n one(events: Record, data: any): Bus;\n one(events: Record, selector: string | null | undefined, data: any): Bus;\n one(events: string, callback: EventCallback): Bus;\n one(events: string, selector: string, callback: EventCallback): Bus;\n one(events: string, data: any, callback: EventCallback): Bus;\n one(events: string, selector: string | null | undefined, data: any, callback: EventCallback): Bus;\n\n off(): Bus;\n off(events: string): Bus;\n off(events: Record): Bus;\n off(events: string, callback: EventCallback): Bus;\n off(events: string, selector: string, callback: EventCallback): Bus;\n\n trigger(event: Event | string, data?: any): Bus;\n }\n}\n\n$.bus = bus;\n$.on = bus.on.bind(bus);\n$.one = bus.one.bind(bus);\n$.off = bus.off.bind(bus);\n$.trigger = bus.trigger.bind(bus);\n","import {$, Cash, Selector} from '../cash';\n\n/**\n * Options for {@link isVisible}.\n */\ntype ISVisibleOptions = {\n /** Whether to check if the element is fully visible. */\n fullyCheck?: boolean;\n viewport?: {left: number, top: number, width: number, height: number} | DOMRectReadOnly\n};\n\n/**\n * Check an element whethear is visible in the current viewport.\n *\n * @param selector Element selector to check.\n * @param options Options.\n * @returns True if the element is visible.\n * @see https://stackoverflow.com/a/26039199\n */\nexport function isVisible(selector: Selector, options?: ISVisibleOptions): boolean {\n const element = $(selector)[0];\n if (!element) {\n return false;\n }\n\n let {viewport} = options || {};\n const {left, top, width, height} = element.getBoundingClientRect();\n if (!viewport) {\n const {innerHeight, innerWidth} = window;\n const {clientHeight, clientWidth} = document.documentElement;\n viewport = {left: 0, top: 0, width: innerWidth || clientWidth, height: innerHeight || clientHeight};\n }\n const {left: viewportLeft, top: viewportTop, width: viewportWidth, height: viewportHeight} = viewport;\n if (options?.fullyCheck) {\n return (\n (left >= viewportLeft)\n && (top >= viewportTop)\n && ((left + width) <= viewportWidth)\n && ((top + height) <= viewportHeight)\n );\n }\n // http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap\n const horInView = (left <= viewportWidth) && ((left + width) >= viewportLeft);\n const vertInView = (top <= viewportHeight) && ((top + height) >= viewportTop);\n\n return vertInView && horInView;\n}\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n isVisible(options?: ISVisibleOptions): boolean;\n }\n}\n\n/* Extend as $.fn.isVisible() */\n$.fn.isVisible = function (this: Cash, options?: ISVisibleOptions) {\n return isVisible(this, options);\n};\n","import {$, Cash} from '../cash';\nimport {nextGid} from '../helpers';\n\nimport type {Selector} from '../cash';\n\n/**\n * Run javascript in an element.\n *\n * @param selector Element selector to run.\n * @param jsCode If not set, run all scripts in the element.\n */\nexport function runJS(selector: Selector, jsCode?: string, removeAfterRun = false) {\n const $element = $(selector);\n if (jsCode !== undefined) {\n if (jsCode.length) {\n const id = `zui-runjs-${nextGid()}`;\n $element.append(``);\n if (removeAfterRun) {\n $element.find(`#${id}`).remove();\n }\n }\n return;\n }\n $element.find('script').each((_, script) => {\n runJS($element, (script as HTMLScriptElement).innerHTML);\n script.remove();\n });\n}\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n runJS(jsCode?: string): this;\n }\n\n interface CashStatic {\n runJS(jsCode: string, ...args: [name: string, value: unknown][]): T;\n }\n}\n\n/* Extend as $.runJS() */\n$.runJS = (jsCode: string, ...args: [name: string, value: unknown][]): T => {\n jsCode = jsCode.trim();\n if (!jsCode.startsWith('return ') && !jsCode.endsWith(';')) {\n jsCode = `return ${jsCode}`;\n }\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const func = new Function(...args.map(([name]) => name), jsCode);\n return func(...args.map(([, value]) => value));\n};\n\n/* Extend as $.fn.runJS() */\n$.fn.runJS = function (this: Cash, jsCode?: string) {\n return this.each((_, ele) => {\n runJS(ele, jsCode);\n });\n};\n","import {$, Cash, Selector} from '../cash';\nimport {isVisible} from './is-visible';\n\n/**\n * Options for {@link scrollIntoView}.\n */\ntype CashScrollIntoViewOptions = ScrollIntoViewOptions & {\n ifNeeded?: boolean;\n};\n\n/**\n * Scroll into view.\n *\n * @param selector Element selector to scroll into view.\n * @param options Options.\n * @returns True if the element is visible.\n * @see https://stackoverflow.com/a/26039199\n */\nexport function scrollIntoView(selector: Selector, options?: CashScrollIntoViewOptions): Cash {\n const $element = $(selector);\n const {ifNeeded = true, ...other} = options || {};\n $element.each((_, ele) => {\n if (ifNeeded) {\n if ((ele as unknown as {scrollIntoViewIfNeeded?: (options: ScrollIntoViewOptions) => void}).scrollIntoViewIfNeeded) {\n return (ele as unknown as {scrollIntoViewIfNeeded: (options: ScrollIntoViewOptions) => void}).scrollIntoViewIfNeeded(other);\n }\n if (isVisible(ele, {viewport: ele.getBoundingClientRect()})) {\n return;\n }\n }\n ele.scrollIntoView(other);\n });\n return $element;\n}\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface Cash {\n scrollIntoView(options?: CashScrollIntoViewOptions): this;\n }\n}\n\n/* Extend as $.fn.scrollIntoView() */\n$.fn.scrollIntoView = function (this: Cash, options?: CashScrollIntoViewOptions) {\n return this.each((_, ele) => {\n scrollIntoView(ele, options);\n });\n};\n","import {$} from '../cash';\n\nexport type GetLibCallback = () => void;\n\nexport type GetLibOptions = {\n src: string;\n id?: string;\n async?: boolean;\n defer?: boolean;\n noModule?: boolean;\n type?: string;\n integrity?: string;\n name?: string;\n root?: string;\n success?: GetLibCallback;\n};\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n libRoot?: string;\n\n libMap?: Record;\n\n setLibRoot(root: string): void;\n\n registerLib(name: string, options: GetLibOptions): void;\n\n getLib(options: GetLibOptions): Promise;\n getLib(src: string): Promise;\n getLib(src: string, options: Omit): Promise;\n getLib(src: string, callback: GetLibCallback): Promise;\n getLib(src: string, options: GetLibCallback, callback?: GetLibCallback): Promise;\n getLib(optionsOrSrc: string | GetLibOptions, optionsOrCallback?: Omit | GetLibCallback, callback?: GetLibCallback): Promise;\n\n /**\n * @deprecated Use $.getLib instead.\n */\n getScript(optionsOrSrc: string | (GetLibOptions & {src: string}), optionsOrCallback?: Omit | GetLibCallback, callback?: GetLibCallback): Promise;\n }\n}\n\n/** Define the $.libRoot property. */\n$.setLibRoot = function (root: string): void {\n $.libRoot = root;\n};\n\n/** Define the $.libMap property. */\n$.registerLib = function (name: string, options: GetLibOptions): void {\n if (!$.libMap) {\n $.libMap = {};\n }\n if (!options.name && options.id) {\n options.id = `zui-lib-${name}`;\n }\n $.libMap[name] = options;\n};\n\n/** Define the $.getLib method. */\n$.getLib = function (optionsOrSrc: string | (GetLibOptions & {src: string}), optionsOrCallback?: Omit | GetLibCallback, callback?: GetLibCallback): Promise {\n return new Promise((resolve, reject) => {\n let options: GetLibOptions = typeof optionsOrSrc === 'string' ? {src: optionsOrSrc} : $.extend({}, optionsOrSrc);\n if (typeof optionsOrCallback === 'function') {\n options.success = optionsOrCallback;\n } else if (optionsOrCallback) {\n $.extend(options, optionsOrCallback);\n }\n if (callback) {\n options.success = callback;\n }\n\n let {src} = options;\n if (!src) {\n return reject(new Error('[ZUI] No src provided for $.getLib.'));\n }\n const lib = $.libMap && $.libMap[src];\n if (lib) {\n options = $.extend({}, lib, options);\n src = lib.src || options.src;\n }\n const {root = $.libRoot} = options;\n if (root) {\n src = `${root}${(root.endsWith('/') && src.startsWith('/')) ? '' : '/'}${src}`;\n }\n\n const {success, name} = options;\n const getLibVar = () => {\n return name ? (window as unknown as Record)[name] : undefined;\n };\n const onSuccess = () => {\n resolve(getLibVar() as T);\n success?.();\n };\n if (getLibVar()) {\n onSuccess();\n return;\n }\n\n const {id} = options;\n const $oldScripts = $(id ? `#${id}` : `script[src=\"${src}\"]`);\n if ($oldScripts.length) {\n if ($oldScripts.dataset('loaded')) {\n onSuccess();\n } else {\n const callbacks = $oldScripts.data('loadCalls') || [];\n callbacks.push(onSuccess);\n $oldScripts.data('loadCalls', callbacks);\n }\n return;\n }\n const {async = true, defer = false, noModule = false, type, integrity} = options;\n const script = document.createElement('script');\n script.async = async;\n script.defer = defer;\n script.noModule = noModule;\n if (type) {\n script.type = type;\n }\n if (integrity) {\n script.integrity = integrity;\n }\n\n script.onload = () => {\n onSuccess();\n const callbacks: GetLibCallback[] = $(script).dataset('loaded', true).data('loadCalls') || [];\n callbacks.forEach(x => x());\n $(script).removeData('loadCalls');\n };\n script.onerror = () => {\n reject(new Error(`[ZUI] Failed to load lib from: ${src}`));\n };\n script.src = src;\n $('head').append(script);\n });\n};\n\n/** Define the $.getScript method. */\n$.getScript = $.getLib;\n","import {$, Cash} from '../cash';\n\n/**\n * Check whether the element is detached from document.\n * @param element The element to check.\n * @returns Whether the element is detached from document.\n */\nexport function isElementDetached(element: Node): boolean {\n if (element.parentNode === document) {\n return false;\n }\n if (!element.parentNode) {\n return true;\n }\n return isElementDetached(element.parentNode);\n}\n\n/* Declare types. */\ndeclare module 'cash-dom' {\n interface CashStatic {\n isDetached(element: Node): boolean;\n }\n\n interface Cash {\n isDetached(): boolean;\n }\n}\n\n/* Extend $.isDetached. */\n$.isDetached = isElementDetached;\n\n/* Extend as $.fn.isDisabled(). */\n$.fn.isDetached = function (this: Cash) {\n const element = this[0];\n return !element || isElementDetached(element);\n};\n","import type {ComponentType} from 'preact';\n\nexport const reactComponents: Record = {};\n\nexport function registerReactComponent

    (name: string, component?: ComponentType

    ): void;\n\nexport function registerReactComponent(componentMap: Record): void;\n\nexport function registerReactComponent(nameOrMap: string | Record, component?: ComponentType): void {\n if (typeof nameOrMap === 'object') {\n Object.keys(nameOrMap).forEach(name => {\n registerReactComponent(name, nameOrMap[name] as ComponentType);\n });\n } else if (component) {\n reactComponents[nameOrMap.toLowerCase()] = component;\n }\n}\n\nexport function getReactComponent

    (name: string): ComponentType

    | undefined {\n return reactComponents[name.toLowerCase()] as (ComponentType

    | undefined);\n}\n","import {h, Component} from 'preact';\nimport {nextGid} from '../../helpers/gid';\nimport {classes} from '../../helpers/classes';\nimport {getReactComponent} from './components';\n\nimport type {JSX, ComponentType, RenderableProps, ComponentChildren} from 'preact';\nimport type {ClassNameLike} from '../../helpers/classes';\nimport type {HElementProps} from '../types';\n\nconst strDangerouslySetInnerHTML = 'dangerouslySetInnerHTML';\n\n/**\n * The base HTML element.\n */\nexport class HElement

    extends Component {\n static HElement = true;\n\n static customProps: string[] = [];\n\n protected _gid = nextGid();\n\n get gid() {\n return this._gid;\n }\n\n get element() {\n return document.querySelector(`[z-gid-${this._gid}]`);\n }\n\n changeState(state: Partial | ((prevState: Readonly) => Partial), callback?: () => void): Promise {\n return new Promise(resolve => {\n this.setState(state, () => {\n callback?.();\n resolve(this.state);\n });\n });\n }\n\n protected _getClassName(props: RenderableProps

    ): ClassNameLike {\n return props.className;\n }\n\n protected _getProps(props: RenderableProps

    ): Record {\n const {className, attrs, props: componentProps, data, forwardRef, children, component, style, class: classNameAlt, ...others} = props;\n const customProps = new Set((this.constructor as typeof HElement).customProps);\n const other = Object.keys(others).reduce>((map, key) => {\n if (!customProps.has(key) && (key === strDangerouslySetInnerHTML || /^(on[A-Z]|data-|zui-|z-)[a-zA-Z-]+/.test(key))) {\n const val = others[key as keyof typeof others];\n map[key] = (key !== strDangerouslySetInnerHTML && val && typeof val === 'object') ? JSON.stringify(val) : val;\n }\n return map;\n }, {});\n return {ref: forwardRef, className: classes(this._getClassName(props), classNameAlt) || undefined, style, [`z-gid-${this._gid}`]: '', ...other, ...attrs, ...componentProps};\n }\n\n protected _getComponent(props: RenderableProps

    ): ComponentType | keyof JSX.IntrinsicElements {\n const {component = 'div'} = props;\n return (typeof component === 'string' ? getReactComponent(component as string) : component) || component;\n }\n\n protected _getChildren(props: RenderableProps

    ): ComponentChildren {\n return props.children;\n }\n\n protected _beforeRender(props: RenderableProps

    ): RenderableProps

    | undefined | void {\n return props;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _onRender(component: ComponentType | keyof JSX.IntrinsicElements, componentProps: Record, children: ComponentChildren, _props: RenderableProps

    ): [component: ComponentType | keyof JSX.IntrinsicElements, componentProps: Record, children: ComponentChildren] | void {\n return [component, componentProps, children];\n }\n\n render(props: RenderableProps

    ) {\n props = this._beforeRender(props) || props;\n let component = this._getComponent(props);\n let children = this._getChildren(props);\n let componentProps = this._getProps(props);\n const renderResult = this._onRender(component, componentProps, children, props);\n if (renderResult) {\n [component, componentProps, children] = renderResult;\n }\n return h(component as ComponentType, componentProps, children);\n }\n}\n","import{options as r}from\"preact\";export{Fragment}from\"preact\";var _=0;function o(o,e,n,t,f,l){var s,u,a={};for(u in e)\"ref\"==u?s=e[u]:a[u]=e[u];var i={type:o,props:a,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:--_,__source:f,__self:l};if(\"function\"==typeof o&&(s=o.defaultProps))for(u in s)void 0===a[u]&&(a[u]=s[u]);return r.vnode&&r.vnode(i),i}export{o as jsx,o as jsxDEV,o as jsxs};\n//# sourceMappingURL=jsxRuntime.module.js.map\n","import {Component, createRef} from 'preact';\nimport {$} from '../../cash';\nimport {HElement} from './h-element';\n\nimport type {HtmlContentProps} from '../types';\n\n/**\n * HTML content component.\n *\n * @example\n * // Render

    Hello world

    \n * Hello world\" />\n *\n * // Render and execute script\n * alert('Hello world')\" executeScript />\n */\nexport class HtmlContent extends Component {\n protected _ref = createRef();\n\n protected _runJS() {\n if (!this.props.executeScript) {\n return;\n }\n $(this._ref.current).runJS();\n }\n\n componentDidMount(): void {\n this._runJS();\n }\n\n componentDidUpdate(previousProps: Readonly): void {\n if (this.props.html !== previousProps.html) {\n this._runJS();\n }\n }\n\n render(props: HtmlContentProps) {\n const {executeScript, html, ...others} = props;\n return ;\n }\n}\n","import {h as _h, isValidElement, ComponentChildren, JSX, Attributes} from 'preact';\nimport {classes, ClassNameLike} from '../../helpers';\n\n/**\n * @deprecated Use `CustomContent` instead.\n */\nexport type CustomRenderResultItem = Partial<{\n html: string;\n __html: string;\n style: JSX.CSSProperties;\n className: ClassNameLike;\n children: ComponentChildren;\n attrs: JSX.HTMLAttributes;\n [prop: string]: unknown;\n}>;\n\n/**\n * @deprecated Use `CustomContent` instead.\n */\nexport type CustomRenderResultGenerator = unknown[], THIS = unknown> = (this: THIS, result: ComponentChildren[], ...args: T) => (ComponentChildren | CustomRenderResultItem)[] | undefined | void;\n\n/**\n * @deprecated Use `CustomContent` instead.\n */\nexport type CustomRenderResult = unknown[], THIS = unknown> = CustomRenderResultGenerator | CustomRenderResultItem | ComponentChildren;\n\n/**\n * @deprecated Use `CustomContent` instead.\n */\nexport type CustomRenderResultList = unknown[], THIS = unknown> = CustomRenderResult[];\n\n/**\n * @deprecated Use `CustomContent` instead.\n */\nexport type CustomRenderProps = unknown[], THIS = unknown> = {\n tag?: string;\n className?: ClassNameLike;\n style?: JSX.CSSProperties;\n renders: CustomRenderResultList;\n generateArgs?: T;\n generators?: Record>;\n generatorThis?: THIS;\n onGenerate?: (this: THIS, generator: CustomRenderResultGenerator, result: ComponentChildren[], ...args: T) => (ComponentChildren | CustomRenderResultItem)[];\n onRenderItem?: (item: CustomRenderResultItem) => ComponentChildren;\n children?: ComponentChildren;\n};\n\n/**\n * @deprecated Use `renderCustomContent` instead.\n */\nexport function renderCustomResult(props: CustomRenderProps): [JSX.HTMLAttributes, ComponentChildren[]] {\n const {\n tag,\n className,\n style,\n renders,\n generateArgs = [],\n generatorThis,\n generators,\n onGenerate,\n onRenderItem,\n ...others\n } = props;\n const classList: ClassNameLike = [className];\n const rootStyle: JSX.CSSProperties = {...style};\n const result: ComponentChildren[] = [];\n const rawHtml: string[] = [];\n renders.forEach(render => {\n const items: (CustomRenderResultItem | ComponentChildren)[] = [];\n if (typeof render === 'string' && generators && generators[render]) {\n render = generators[render];\n }\n if (typeof render === 'function') {\n if (onGenerate) {\n items.push(...onGenerate.call(generatorThis, render as CustomRenderResultGenerator, result, ...generateArgs));\n } else {\n const renderResult = (render as CustomRenderResultGenerator).call(generatorThis, result, ...generateArgs);\n if (renderResult) {\n if (Array.isArray(renderResult)) {\n items.push(...renderResult);\n } else {\n items.push(renderResult);\n }\n }\n }\n } else {\n items.push(render);\n }\n items.forEach(item => {\n if (item === undefined || item === null) {\n return;\n }\n if (typeof item === 'object' && !isValidElement(item) && ('html' in item || '__html' in item || 'className' in item || 'style' in item || 'attrs' in item || 'children' in item)) {\n if (item.html) {\n result.push(\n
    )}>
    ,\n );\n } else if (item.__html) {\n rawHtml.push(item.__html);\n } else {\n if (item.style) {\n Object.assign(rootStyle, item.style);\n }\n if (item.className) {\n classList.push(item.className);\n }\n if (item.children) {\n result.push(item.children);\n }\n if (item.attrs) {\n Object.assign(others, item.attrs);\n }\n }\n } else {\n result.push(item);\n }\n });\n });\n\n if (rawHtml.length) {\n Object.assign(others, {dangerouslySetInnerHTML: {__html: rawHtml}});\n }\n\n return [{\n className: classes(classList),\n style: rootStyle,\n ...others,\n }, result];\n}\n\n/**\n * @deprecated Use `CustomContent` instead.\n */\nexport function CustomRender({\n tag = 'div',\n ...props\n}: CustomRenderProps) {\n const [attrs, children] = renderCustomResult(props);\n return _h(tag, attrs as Attributes, ...children);\n}\n","import {isValidElement} from 'preact';\nimport {HtmlContent} from './html-content';\nimport {HElement} from './h-element';\nimport {mergeProps} from '../../helpers';\n\nimport type {ComponentChildren, VNode} from 'preact';\nimport type {HtmlContentProps, HElementProps, CustomContentType, CustomContentGenerator, CustomContentProps} from '../types';\n\n/**\n * Render custom content.\n *\n * @param content The content to render.\n * @param generatorThis The `this` value to use when calling the generator.\n * @param generatorArgs The arguments to pass to the generator.\n * @returns The rendered content.\n */\nexport function renderCustomContent(props: CustomContentProps): ComponentChildren {\n const {content: contentSetting, generatorArgs, generatorThis, ...others} = props;\n let content = contentSetting;\n if (typeof content === 'function') {\n content = (content as CustomContentGenerator).call(generatorThis, ...(generatorArgs || []));\n }\n if (Array.isArray(content)) {\n return content.map((x) => renderCustomContent({...others, content: x, generatorThis, generatorArgs}));\n }\n if ((typeof content === 'string' || typeof content === 'number')) {\n if (Object.keys(others).length) {\n return
    {content}
    ;\n }\n return content;\n }\n if (content && typeof content === 'object' && (typeof (content as HtmlContentProps).html === 'string' || (content as HtmlContentProps).component)) {\n if ((content as HtmlContentProps).html) {\n return ;\n }\n let {children} = content as HElementProps;\n if (children) {\n children = Array.isArray(children) ? children : [children];\n content = mergeProps({children: (children as CustomContentType[]).map((x) => renderCustomContent({...others, content: x, generatorThis, generatorArgs}))}, content);\n }\n return ;\n }\n if (isValidElement(content)) {\n return content;\n }\n if (content) {\n console.groupCollapsed('[ZUI] CustomContent format error');\n console.trace('content:', content);\n console.log('props:', props);\n console.groupEnd();\n }\n return null;\n}\n\n/**\n * Component for rendering custom content.\n *\n * @param props Custom content props.\n * @returns Custom content.\n */\nexport function CustomContent(props: CustomContentProps): VNode | null {\n const result = renderCustomContent(props);\n if (result === undefined || result === null || typeof result === 'boolean') {\n return null;\n }\n if (isValidElement(result)) {\n return result;\n }\n return <>{result};\n}\n","import {isValidElement} from 'preact';\nimport {classes} from '../../helpers/classes';\n\nimport type {ClassNameLike} from '../../helpers/classes';\nimport type {IconProps} from '../types';\n\nconst createIconClass = (icon: string) => icon.startsWith('icon-') ? icon : `icon-${icon}`;\n\n/**\n * Component for rendering icons.\n *\n * @param props Icon properties.\n * @returns Icon element.\n */\nexport function Icon(props: IconProps) {\n const {icon, className, ...others} = props;\n if (!icon) {\n return null;\n }\n if (isValidElement(icon)) {\n return icon;\n }\n const classList: ClassNameLike[] = ['icon', className as string];\n if (typeof icon === 'string') {\n classList.push(createIconClass(icon));\n } else if (typeof icon === 'object') {\n const {className: iconClass, icon: finalIcon, ...iconOthers} = icon;\n classList.push(iconClass as string, finalIcon ? createIconClass(finalIcon as string) : '');\n Object.assign(others, iconOthers);\n }\n return ;\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {createElement, render} from 'preact';\n\nimport type {VNode, RenderableProps, ContainerNode} from 'preact';\n\n/**\n * @param {import('../../src/index').RenderableProps<{ context: any }>} props\n */\nfunction ContextProvider(this: any, props: RenderableProps<{context: any}>) {\n this.getChildContext = () => props.context;\n return props.children;\n}\n\n/**\n * Portal component\n * @this {import('preact').Component}\n * @param {object | null | undefined} props\n *\n * TODO: use createRoot() instead of fake root\n */\nexport function Portal(this: any, props: any) {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const that = this;\n const container = props._container;\n\n that.componentWillUnmount = function () {\n render(null, that._temp);\n that._temp = null;\n that._container = null;\n };\n\n // When we change container we should clear our old container and\n // indicate a new mount.\n if (that._container && that._container !== container) {\n that.componentWillUnmount();\n }\n\n // When props.vnode is undefined/false/null we are dealing with some kind of\n // conditional vnode. This should not trigger a render.\n if (props._vnode) {\n if (!that._temp) {\n that._container = container;\n\n // Create a fake DOM parent node that manages a subset of `container`'s children:\n that._temp = {\n nodeType: 1,\n parentNode: container,\n childNodes: [],\n appendChild(child: VNode) {\n this.childNodes.push(child);\n that._container.appendChild(child);\n },\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n insertBefore(child: VNode, _before: VNode) {\n this.childNodes.push(child);\n that._container.appendChild(child);\n },\n removeChild(child: VNode) {\n this.childNodes.splice(this.childNodes.indexOf(child) >>> 1, 1);\n that._container.removeChild(child);\n },\n };\n }\n\n // Render our wrapping element into temp.\n render(\n createElement(ContextProvider as any, {context: that.context}, props._vnode),\n that._temp,\n );\n } else if (that._temp) {\n // When we come from a conditional render, on a mounted\n // portal we should clear the DOM.\n that.componentWillUnmount();\n }\n}\n\n/**\n * Create a `Portal` to continue rendering the vnode tree at a different DOM node\n *\n * @param {import('preact').VNode} vnode The vnode to render\n * @param {import('preact').PreactElement} container The DOM node to continue rendering in to.\n * @see https://github.com/developit/preact-portal/blob/master/src/preact-portal.js\n */\nexport function createPortal(vnode: VNode, container: ContainerNode): VNode {\n const el = createElement(Portal as any, {_vnode: vnode, _container: container}) as any;\n el.containerInfo = container;\n return el;\n}\n","import {HElement} from './h-element';\nimport {HtmlContent} from './html-content';\nimport {CustomContent} from './custom-content';\nimport {Icon} from './icon';\nimport {Portal} from './portals';\nimport {registerReactComponent} from './components';\n\nregisterReactComponent({\n HElement,\n element: HElement,\n HtmlContent,\n html: HtmlContent,\n CustomContent,\n custom: CustomContent,\n Icon,\n Portal,\n});\n","import {i18n} from '../i18n';\nimport {$} from '../cash';\nimport {nextGid} from '../helpers';\nimport {isElementDetached} from '../dom/is-detached';\n\nimport type {Cash, Element, Selector} from '../cash';\nimport type {ComponentEventArgs, ComponentEventName, ComponentOptions, ComponentEvents, ComponentEventsDefnition} from './types';\n\n/**\n * The event callback for component.\n */\nexport type ComponentEventCallback> = (event: N extends keyof HTMLElementEventMap ? HTMLElementEventMap[N] : Event, args: [Component, ComponentEventArgs]) => void | false;\n\n/**\n * The component base class.\n */\nexport class Component {\n /**\n * The default options.\n */\n static DEFAULT = {};\n\n /**\n * The component name.\n * It usually equals to the class name.\n * The name must be provided in subclass.\n */\n static NAME: string;\n\n /**\n * Whether the component supports multiple instances.\n */\n static MULTI_INSTANCE = false;\n\n /**\n * ZUI name\n */\n static get ZUI() {\n return this.NAME.replace(/(^[A-Z]+)/, (match) => match.toLowerCase());\n }\n\n /**\n * Component data key, like \"zui.menu\"\n */\n static get KEY(): `zui.${string}` {\n return `zui.${this.NAME}`;\n }\n\n /**\n * Component namespace, like \".zui.menu\"\n */\n static get NAMESPACE(): `.zui.${string}` {\n return `.zui.${this.ZUI}`;\n }\n\n static get DATA_KEY(): `data-zui-${string}` {\n return `data-zui-${this.NAME}`;\n }\n\n /**\n * Access to static properties via this.constructor.\n *\n * @see https://github.com/Microsoft/TypeScript/issues/3841#issuecomment-337560146\n */\n declare ['constructor']: typeof Component;\n\n /**\n * Store the component options.\n */\n private _options?: ComponentOptions;\n\n /**\n * Store the component element.\n */\n private _element?: U;\n\n /**\n * The component global ID.\n */\n private _gid: number;\n\n /**\n * The component key.\n */\n protected _key: string | number;\n\n /**\n * The component initialized flag.\n */\n private _inited = false;\n\n /**\n * Auto destroy flag.\n */\n private _autoDestory = 0;\n\n /**\n * Element removed observer.\n */\n private _mobs?: MutationObserver;\n\n /**\n * The component constructor.\n *\n * @param options The component initial options.\n */\n constructor(selector: Selector, options?: Partial>) {\n const {KEY, DATA_KEY, DEFAULT, MULTI_INSTANCE, NAME} = this.constructor;\n\n if (!NAME) {\n throw new Error('[ZUI] The component must have a \"NAME\" static property.');\n }\n\n const $element = $(selector);\n if ($element.data(KEY) && !MULTI_INSTANCE) {\n throw new Error('[ZUI] The component has been initialized on element.');\n }\n\n const element = $element[0] as U;\n const gid = nextGid();\n this._gid = gid;\n this._element = element;\n\n const $parent = $element.parent();\n if ($parent.length) {\n this._mobs = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.removedNodes.forEach(ele => {\n if (ele !== element) {\n return;\n }\n if (this._autoDestory) {\n clearTimeout(this._autoDestory);\n }\n this._autoDestory = window.setTimeout(() => {\n this._autoDestory = 0;\n if (isElementDetached(element)) {\n this.destroy();\n }\n }, 100);\n });\n });\n });\n this._mobs.observe($parent[0]!, {childList: true, subtree: false});\n }\n\n this._options = {...DEFAULT, ...$element.dataset()} as ComponentOptions;\n this.setOptions(options);\n this._key = this.options.key ?? `__${gid}`;\n\n $element.data(KEY, this).attr(DATA_KEY, `${gid}`);\n if (MULTI_INSTANCE) {\n const dataName = `${KEY}:ALL`;\n let instanceMap = $element.data(dataName);\n if (!instanceMap) {\n instanceMap = new Map();\n $element.data(dataName, instanceMap);\n }\n instanceMap.set(this._key, this);\n }\n\n this.init();\n requestAnimationFrame(async () => {\n this._inited = true;\n await this.afterInit();\n this.emit('inited', this.options);\n });\n }\n\n get inited() {\n return this._inited;\n }\n\n /**\n * Get the component element.\n */\n get element() {\n return this._element!;\n }\n\n get key() {\n return this._key;\n }\n\n /**\n * Get the component options.\n */\n get options() {\n return this._options!;\n }\n\n /**\n * Get the component global id.\n */\n get gid() {\n return this._gid;\n }\n\n /**\n * Get the component element as a jQuery like object.\n */\n get $element() {\n return $(this.element);\n }\n\n /**\n * Get the component event emitter.\n */\n get $emitter() {\n return this.$element;\n }\n\n /**\n * Initialize the component.\n */\n init() {}\n\n /**\n * Do something after the component initialized.\n */\n afterInit(): void | Promise {}\n\n /**\n * Render the component.\n *\n * @param options The component options to override before render.\n */\n render(options?: Partial>) {\n this.setOptions(options);\n }\n\n /**\n * Destroy the component.\n */\n destroy() {\n const {KEY, DATA_KEY, MULTI_INSTANCE} = this.constructor;\n const {$element} = this;\n\n (this.emit as ((event: string, ...args: unknown[]) => void))('destroyed');\n\n this._mobs?.disconnect();\n\n $element\n .off(this.namespace)\n .removeData(KEY)\n .attr(DATA_KEY, null);\n\n if (MULTI_INSTANCE) {\n const map = this.$element.data(`${KEY}:ALL`) as Map>;\n if (map) {\n map.delete(this._key);\n if (map.size === 0) {\n this.$element.removeData(`${KEY}:ALL`);\n } else {\n const nextInstance = map.values().next().value;\n $element.data(KEY, nextInstance).attr(DATA_KEY, nextInstance.gid);\n }\n }\n }\n }\n\n /**\n * Set the component options.\n *\n * @param options The component options to set.\n * @returns The component options.\n */\n setOptions(options?: Partial>): ComponentOptions {\n if (options) {\n $.extend(this._options, options);\n }\n return this._options!;\n }\n\n /**\n * Emit a component event.\n * @param event The event name.\n * @param args The event arguments.\n */\n emit>(event: N, ...args: ComponentEventArgs): Event {\n const eventObject = $.Event(event);\n (eventObject as unknown as {__src?: unknown}).__src = this;\n this.$emitter.trigger(eventObject, [this, ...args]);\n return eventObject as unknown as Event;\n }\n\n /**\n * Listen to a component event.\n *\n * @param event The event name.\n * @param callback The event callback.\n */\n on>(event: N | (string & {}), callback: ComponentEventCallback, options?: {once?: boolean}) {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const component = this;\n this.$element[options?.once ? 'one' : 'on'](this._wrapEvent(event), function (this: Component, e: N extends keyof HTMLElementEventMap ? HTMLElementEventMap[N] : Event, info: [Component, ComponentEventArgs]) {\n if (!(e as {__src?: unknown}).__src || (e as {__src?: unknown}).__src === component) {\n callback.call(this, e, info);\n }\n });\n }\n\n /**\n * Listen to a component event.\n *\n * @param event The event name.\n * @param callback The event callback.\n */\n one>(event: N, callback: ComponentEventCallback) {\n this.on(event, callback, {once: true});\n }\n\n /**\n * Stop listening to a component event.\n * @param event The event name.\n * @param callback The event callback.\n */\n off>(event: N | (string & {})) {\n this.$element.off(this._wrapEvent(event));\n }\n\n /**\n * Get the i18n text.\n *\n * @param key The i18n key.\n * @param defaultValue The default value if the key is not found.\n */\n i18n(key: string, defaultValue?: string): string;\n\n /**\n * Get the i18n text.\n *\n * @param key The i18n key.\n * @param args The i18n arguments.\n * @param defaultValue The default value if the key is not found.\n */\n i18n(key: string, args?: (string | number)[] | Record, defaultValue?: string): string;\n\n /**\n * Get the i18n text.\n *\n * @param key The i18n key.\n * @param args The i18n arguments or the default value.\n * @param defaultValue The default value if the key is not found.\n * @returns The i18n text.\n */\n i18n(key: string, args?: string | (string | number)[] | Record, defaultValue?: string): string {\n return i18n(this.options.i18n, key, args, defaultValue, this.options.lang, this.constructor.NAME)\n ?? i18n(this.options.i18n, key, args, defaultValue, this.options.lang)\n ?? `{i18n:${key}}`;\n }\n\n /**\n * Get event namespace.\n * @returns Event namespace.\n */\n get namespace(): `.zui.${string}` {\n return `${this.constructor.NAMESPACE}.${this._key}`;\n }\n\n /**\n * Wrap event names with component namespace.\n *\n * @param names The event names.\n * @returns The wrapped event names.\n */\n protected _wrapEvent(names: string) {\n return names.split(' ').map(name => name.includes('.') ? name : `${name}${this.namespace}`).join(' ');\n }\n\n /**\n * Get the component instance of the given element.\n *\n * @param this Current component constructor.\n * @param selector The component element selector.\n * @returns The component instance.\n */\n static get>(this: T, selector: Selector, key?: string | number): InstanceType | undefined {\n const $element = $(selector);\n if (this.MULTI_INSTANCE && key !== undefined) {\n const instanceMap = $element.data(`${this.KEY}:ALL`);\n if (instanceMap) {\n return instanceMap.get(key);\n }\n return;\n }\n return $element.data(this.KEY);\n }\n\n /**\n * Ensure the component instance of the given element.\n *\n * @param this Current component constructor.\n * @param selector The component element selector.\n * @param options The component options.\n * @returns The component instance.\n */\n static ensure>(this: T, selector: Selector, options?: Partial>): InstanceType {\n const instance = this.get(selector, options?.key);\n if (instance) {\n if (options) {\n instance.setOptions(options);\n }\n return instance;\n }\n return new this(selector, options) as InstanceType;\n }\n\n /**\n * Get all component instances.\n *\n * @param this Current component constructor.\n * @param selector The component element selector.\n * @returns All component instances.\n */\n static getAll>(this: T, selector?: Selector): InstanceType[] {\n const {MULTI_INSTANCE, DATA_KEY} = this;\n const list: InstanceType[] = [];\n $(selector || document)\n .find(`[${DATA_KEY}]`)\n .each((_, element) => {\n if (MULTI_INSTANCE) {\n const instanceMap = $(element).data(`${this.KEY}:ALL`);\n if (instanceMap) {\n list.push(...instanceMap.values());\n return;\n }\n }\n const instance = $(element).data(this.KEY);\n if (instance) {\n list.push(instance);\n }\n });\n return list.sort((a, b) => a.gid - b.gid);\n }\n\n /**\n * Query the component instance.\n *\n * @param this Current component constructor.\n * @param selector The component element selector.\n * @returns The component instance.\n */\n static query>(this: T, selector?: Selector, key?: string | number, filter?: (instance: InstanceType, index: number) => boolean): InstanceType | undefined {\n if (selector === undefined) {\n let all = this.getAll();\n if (filter) {\n all = all.filter(filter);\n }\n return all.pop();\n }\n return this.get($(selector).closest(`[${this.DATA_KEY}]`), key);\n }\n\n /**\n * Create cash fn.method for current component.\n *\n * @param name The method name.\n */\n static defineFn(name?: string) {\n let fnName = (name || this.ZUI) as keyof Cash;\n if ($.fn[fnName]) {\n fnName = `zui${this.NAME}` as keyof Cash;\n }\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const ZUIComponent = this;\n $.fn.extend({\n [fnName](options: Partial> | string, ...args: unknown[]) {\n const initOptions = typeof options === 'object' ? options : undefined;\n const callMethod = typeof options === 'string' ? options : undefined;\n let callResult: unknown;\n this.each((_: number, element: Element) => {\n let instance = ZUIComponent.get(element);\n if (instance) {\n if (initOptions) {\n instance.render(initOptions);\n }\n } else {\n instance = new ZUIComponent(element, initOptions);\n }\n if (callMethod) {\n let method: ((...args: unknown[]) => void) = (instance as unknown as Record void>)[callMethod];\n let callThis: unknown = instance;\n if (method === undefined) {\n callThis = (instance as unknown as {$: Record void>}).$;\n method = (callThis as Record void>)[callMethod as string];\n }\n if (typeof method === 'function') {\n callResult = method.call(callThis, ...args);\n } else {\n callResult = method;\n }\n }\n });\n return callResult !== undefined ? callResult : this;\n },\n });\n }\n}\n","import {createRef, render, h} from 'preact';\nimport {Component as ComponentBase} from '../component';\nimport {mergeProps} from '../helpers';\n\nimport type {ComponentEventsDefnition} from '../component';\nimport type {Component as ComponentReact, ComponentClass} from 'preact';\n\nexport class ComponentFromReact = ComponentReact, E extends ComponentEventsDefnition = {}, U extends HTMLElement = HTMLElement> extends ComponentBase {\n /**\n * The React component class.\n */\n static Component: unknown;\n\n /**\n * Whether replace the element.\n */\n static replace: boolean | keyof HTMLElementTagNameMap | (string & {}) = false;\n\n /**\n * Access to static properties via this.constructor.\n *\n * @see https://github.com/Microsoft/TypeScript/issues/3841#issuecomment-337560146\n */\n declare ['constructor']: typeof ComponentFromReact;\n\n /**\n * The React ref for component instance.\n */\n protected _ref = createRef();\n\n /**\n * The React component instance.\n */\n get $(): C | null {\n return this._ref.current;\n }\n\n /**\n * Render after component init.\n */\n afterInit() {\n this.render();\n }\n\n /**\n * Destroy component.\n */\n destroy() {\n this.$?.componentWillUnmount?.();\n if (this.element) {\n this.element.innerHTML = '';\n }\n super.destroy();\n }\n\n /**\n * Render component.\n *\n * @param options new options.\n */\n render(options?: Partial) {\n const {element} = this;\n const {Component, replace} = this.constructor;\n const {$replace = replace, ...userOptions} = this.setOptions(options);\n const props = {\n ref: this._ref,\n ...userOptions,\n };\n if ($replace && (Component as {HElement?: boolean}).HElement && (element.tagName.toLowerCase() === $replace || $replace === true)) {\n const attrs = Array.from(element.attributes).reduce>((data, attribute) => {\n const {name, value} = attribute;\n data[name === 'class' ? 'className' : name] = value;\n return data;\n }, {});\n return render(\n h(Component as ComponentClass, mergeProps({component: element.tagName.toLowerCase(), attrs}, props)),\n element.parentElement!,\n element,\n );\n }\n render(\n h(Component as ComponentClass, props),\n element,\n );\n }\n}\n","import {HElement, Icon, classes} from '@zui/core';\n\nimport type {ClassNameLike} from '@zui/core';\nimport type {ButtonProps} from '../types/button-props';\nimport type {RenderableProps} from 'preact';\n\nexport class Button

    extends HElement

    {\n protected declare _isEmptyText?: boolean;\n\n protected declare _onlyCaret?: boolean;\n\n protected _beforeRender(props: RenderableProps

    ) {\n const {text, loading, loadingText, caret, icon, trailingIcon, children} = props;\n this._isEmptyText = text === undefined || text === null || (typeof text === 'string' && !text.length) || loading && !loadingText;\n this._onlyCaret = caret && this._isEmptyText && !icon && !trailingIcon && !children && !loading;\n }\n\n protected _getChildren(props: RenderableProps

    ) {\n const {loading, loadingIcon, loadingText, icon, text, children, trailingIcon, caret} = props;\n return [\n loading ? : ,\n this._isEmptyText ? null : {loading ? loadingText : text},\n loading ? null : children,\n loading ? null : ,\n loading ? null : caret ? : null,\n ];\n }\n\n protected _getClassName(props: RenderableProps

    ) {\n const {type, className, disabled, loading, active, children, square, size, rounded} = props;\n return ['btn', type, className, {\n 'btn-caret': this._onlyCaret,\n disabled: disabled || loading,\n active,\n loading,\n square: square === undefined ? (!this._onlyCaret && !children && this._isEmptyText) : square,\n }, size ? `size-${size}` : '', typeof rounded === 'string' ? `rounded-${rounded}` : {rounded}];\n }\n\n protected _getComponent(props: RenderableProps

    ) {\n return props.component || (props.url ? 'a' : 'button');\n }\n\n protected _getProps(props: RenderableProps

    ) {\n const component = this._getComponent(props);\n const {url, target, disabled, btnType = 'button', hint} = props;\n const asLink = component === 'a';\n const componentProps: Record = {\n ...super._getProps(props),\n disabled,\n title: hint,\n };\n if (btnType) {\n if (['button', 'reset', 'submit'].includes(btnType)) {\n if (component === 'button') {\n componentProps.type = btnType;\n }\n } else {\n componentProps.className = classes([componentProps.className as ClassNameLike, btnType]);\n }\n }\n if (!disabled) {\n if (url !== undefined) {\n componentProps[asLink ? 'href' : 'data-url'] = url;\n }\n if (target !== undefined) {\n componentProps[asLink ? 'target' : 'data-target'] = target;\n }\n }\n return componentProps;\n }\n}\n","import {registerReactComponent} from '@zui/core';\nimport * as components from './index';\n\nregisterReactComponent(components);\n","import {CustomContent, HElement, mergeProps} from '@zui/core';\n\nimport type {ComponentChild, ComponentChildren, ComponentType, JSX, RenderableProps} from 'preact';\nimport type {ClassNameLike} from '../../../core/src/helpers';\nimport type {CommonListProps, Item, ItemKey, ItemType} from '../types';\n\n/**\n * Generic list component.\n */\nexport class CommonList

    extends HElement {\n /**\n * Root element default name, used for class name.\n */\n static NAME = '';\n\n /**\n * Item default name, used for class name.\n */\n static ITEM_NAME = 'item';\n\n /**\n * Root element default tag name, used for DOM rendering.\n */\n static TAG = 'ul';\n\n /**\n * Item components, used for rendering for different item types.\n */\n static ItemComponents: Partial | ((this: CommonList, item: Item, props: CommonListProps) => Partial)]>> = {\n default: HElement,\n divider: [HElement, {className: 'divider'}],\n space: [HElement, (item) => {\n const {space, flex, style} = item as {space: JSX.CSSProperties['width'], flex: JSX.CSSProperties['flex'], style: JSX.CSSProperties};\n return {\n style: {width: space, height: space, flex, ...style},\n };\n }],\n };\n\n /**\n * Item default common props, used for rendering for all item types.\n */\n static defaultItemProps: Partial = {\n component: 'li',\n };\n\n /**\n * Item default props, used for rendering for different item types.\n */\n static defaultItemPropsMap: Partial>> = {};\n\n /**\n * Item default type, used for rendering for item without type.\n */\n static defaultItemType = 'item';\n\n /**\n * Access to static properties via this.constructor.\n *\n * @see https://github.com/Microsoft/TypeScript/issues/3841#issuecomment-337560146\n */\n declare ['constructor']: typeof CommonList;\n\n /**\n * Store the raw items.\n */\n protected declare _items: Item[];\n\n /**\n * Store the rendered items.\n */\n protected declare _renderedItems: Item[];\n\n constructor(props: P) {\n super(props);\n this._handleClick = this._handleClick.bind(this);\n }\n\n /**\n * Get the root element name, used for class name.\n */\n get name() {\n return this.props.name || this.constructor.NAME;\n }\n\n /**\n * Get the item element name, used for class name.\n */\n get itemName() {\n return this.props.itemName || this.constructor.ITEM_NAME;\n }\n\n getItems() {\n return this._items;\n }\n\n getRenderedItem(key: ItemKey) {\n return this._renderedItems.find((item) => item.key === key);\n }\n\n getItem(key: ItemKey): Item | undefined {\n return this._items[this.getItemIndex(key)];\n }\n\n getItemIndex(key: ItemKey) {\n return this._renderedItems.findIndex((item) => item.key === key);\n }\n\n getItemByIndex(index: number) {\n return this._items[index];\n }\n\n /**\n * Get the item key by index.\n *\n * @param index The rendered item index.\n * @returns The item key, if the item is not rendered, return undefined.\n */\n getKey(index: number): ItemKey | undefined {\n return this._renderedItems?.[index]?.key;\n }\n\n protected _getItemFromEvent(event: MouseEvent): {\n index: number;\n item: Item;\n renderedItem: Item;\n element: HTMLElement;\n event: MouseEvent;\n key: ItemKey;\n relativeTarget?: unknown;\n } | undefined {\n const element = (event.target as HTMLElement).closest('[z-item]') as HTMLElement;\n if (!element || !element.parentElement?.hasAttribute(`z-gid-${this._gid}`)) {\n return;\n }\n const index = +element.getAttribute('z-item')!;\n const item = this._items[index];\n if (!item) {\n return;\n }\n const key = this.getKey(index);\n if (key === undefined) {\n return;\n }\n const renderedItem = this._renderedItems[index];\n return {index, item, element, event, key, renderedItem, relativeTarget: this.props.relativeTarget};\n }\n\n protected _handleClick(event: MouseEvent) {\n const info = this._getItemFromEvent(event);\n if (!info) {\n return;\n }\n this.props.onClickItem?.call(this, info);\n info.item.onClick?.call(this, event, info);\n return info;\n }\n\n /**\n * Render the item content.\n *\n * @param props Current list properties.\n * @param item The item to render.\n * @param index The item index.\n * @returns The item rendered content.\n */\n protected _renderItem(props: RenderableProps

    , item: Item, index: number): ComponentChildren {\n const {beforeRenderItem} = props;\n if (beforeRenderItem) {\n const result = beforeRenderItem.call(this, item, index);\n if (result !== undefined) {\n item = result;\n }\n }\n\n const {type} = item;\n let {itemRender} = props;\n if (itemRender && typeof itemRender === 'object') {\n itemRender = itemRender[type!];\n }\n if (itemRender) {\n const customResult = itemRender.call(this, item, index);\n if (customResult !== undefined) {\n return ;\n }\n }\n\n const {ItemComponents} = this.constructor;\n let ItemComponent = ItemComponents[type!] || ItemComponents.default || HElement;\n if (Array.isArray(ItemComponent)) {\n let defaultItemProps = ItemComponent[1];\n if (typeof defaultItemProps === 'function') {\n defaultItemProps = defaultItemProps.call(this as CommonList, item, props);\n }\n item = mergeProps({}, defaultItemProps, item);\n ItemComponent = ItemComponent[0];\n }\n return ;\n }\n\n /**\n * Get the rendered item final properties.\n *\n * @param props Current list properties.\n * @param item The item to render.\n * @param index The item index.\n * @returns The item to rendered, if return false, the item will not be rendered.\n */\n protected _getItem(props: RenderableProps

    , item: Item, index: number): Item | false {\n if (!item) {\n return false;\n }\n const {itemProps, itemPropsMap = {}, getItem, itemKey = 'id'} = props;\n const {type = this.constructor.defaultItemType} = item;\n const {name, itemName} = this;\n const {defaultItemProps = {}, defaultItemPropsMap = {}} = this.constructor;\n\n item = mergeProps(\n {type},\n defaultItemProps,\n defaultItemPropsMap[type],\n itemProps,\n itemPropsMap[type],\n {className: [name ? `${name}-${type}` : '', itemName]},\n item,\n {\n _item: item,\n _index: index,\n key: String((itemKey ? item[itemKey] : item.key) ?? (item.key ?? index)),\n onClick: undefined,\n },\n );\n\n if (getItem) {\n const result = getItem.call(this, item, index);\n if (result !== undefined) {\n return result;\n }\n }\n return item;\n }\n\n protected _getProps(props: RenderableProps

    ): Record {\n const finalProps = super._getProps(props);\n return {onClick: this._handleClick, ...finalProps};\n }\n\n /**\n * Get the list root element classname list.\n *\n * @param props Current list properties.\n * @returns The list root element classname list.\n */\n protected _getClassName(props: RenderableProps

    ): ClassNameLike {\n return [this.name, props.className];\n }\n\n /**\n * Get final rendered item list.\n *\n * @param props Current list properties.\n * @returns Item list.\n */\n protected _getItems(props: RenderableProps

    ): Item[] {\n let {items = []} = props;\n if (typeof items === 'function') {\n items = items.call(this);\n } else if (!Array.isArray(items)) {\n items = [];\n }\n return items as Item[];\n }\n\n /**\n * Render items.\n *\n * @param props props Current list properties.\n * @param items Render items.\n * @returns React render children.\n */\n protected _renderItems(props: RenderableProps

    , items: Item[]): ComponentChild[] {\n this._renderedItems = items.map((item, index) => {\n const finalItem = this._getItem(props, item, index);\n return finalItem ? finalItem : undefined;\n }) as Item[];\n return this._renderedItems.reduce((children, item, index) => {\n if (item) {\n children.push(this._renderItem(props, item, index));\n }\n return children;\n }, []);\n }\n\n /**\n * Get root element rendered children.\n *\n * @param props Current list properties.\n * @returns React render children.\n */\n protected _getChildren(props: RenderableProps

    ): ComponentChildren {\n const items = this._getItems(props);\n this._items = items;\n const children = this._renderItems(props, items);\n if (props.children) {\n children.push(props.children);\n }\n return children;\n }\n\n /**\n * Get root element rendered component type.\n *\n * @param props Current list properties.\n * @returns React component type.\n */\n protected _getComponent(props: RenderableProps

    ): ComponentType | keyof JSX.IntrinsicElements {\n return props.component || (this.constructor.TAG as keyof JSX.IntrinsicElements);\n }\n}\n","import {ComponentFromReact} from '@zui/core';\nimport {CommonList as CommonListReact} from '../component';\n\nimport type {CommonListProps} from '../types';\n\nexport class CommonList extends ComponentFromReact {\n static NAME = 'CommonList';\n\n static Component = CommonListReact;\n\n static replace = CommonListReact.TAG;\n}\n","import {registerReactComponent} from '@zui/core';\nimport * as components from './index';\n\nregisterReactComponent(components);\n","export type RGBColor = [r: number, g: number, b: number];\n\nexport function hex2Rgb(hex: string): RGBColor {\n if (hex.indexOf('#') === 0) {\n hex = hex.slice(1);\n }\n // convert 3-digit hex to 6-digits.\n if (hex.length === 3) {\n hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n }\n if (hex.length !== 6) {\n throw new Error(`Invalid HEX color \"${hex}\".`);\n }\n return [\n parseInt(hex.slice(0, 2), 16), // r\n parseInt(hex.slice(2, 4), 16), // g\n parseInt(hex.slice(4, 6), 16), // b\n ];\n}\n\nexport function isLightColor(color: string | RGBColor): boolean {\n const [r, g, b] = typeof color === 'string' ? hex2Rgb(color) : color;\n return (r * 0.299 + g * 0.587 + b * 0.114) > 186;\n}\n\nexport function contrastColor(color: string | RGBColor, options?: {dark: string, light: string}) {\n return isLightColor(color) ? (options?.dark ?? '#333333') : (options?.light ?? '#ffffff');\n}\n\nfunction clamp(value: number, max = 255): number {\n return Math.min(Math.max(value, 0), max);\n}\n\nexport function hslToRgb(h: number, s: number, l: number): RGBColor {\n h = (h % 360) / 360;\n s = clamp(s);\n l = clamp(l);\n\n const m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;\n const m1 = l * 2 - m2;\n\n const hue = (value: number): number => {\n value = value < 0 ? value + 1 : (value > 1 ? value - 1 : value);\n if (value * 6 < 1) {\n return m1 + (m2 - m1) * value * 6;\n } else if (value * 2 < 1) {\n return m2;\n } else if (value * 3 < 2) {\n return m1 + (m2 - m1) * (2 / 3 - value) * 6;\n } else {\n return m1;\n }\n };\n\n return [\n hue(h + 1 / 3) * 255,\n hue(h) * 255,\n hue(h - 1 / 3) * 255,\n ];\n}\n","export function getUniqueCode(str: string): number {\n let code = 0;\n if (typeof str !== 'string') str = String(str);\n if (str && str.length) {\n for (let i = 0; i < str.length; ++i) {\n code += (i + 1) * str.charCodeAt(i);\n }\n }\n return code;\n}\n","import {Component, ComponentChildren, JSX} from 'preact';\nimport {classes, Icon} from '@zui/core';\nimport {contrastColor, hslToRgb} from '@zui/helpers/src/color-helper';\nimport {getUniqueCode} from '@zui/helpers/src/string-code';\nimport {AvatarOptions} from '../types/';\n\nfunction getAvatarText(text: string, maxTextLength: number) {\n if (/^[\\u4e00-\\u9fa5\\s]+$/.test(text)) {\n return text.length <= maxTextLength ? text : text.substring(text.length - maxTextLength);\n }\n if (/^[A-Za-z\\d\\s]+$/.test(text)) {\n return text[0].toUpperCase();\n }\n return text.length <= maxTextLength ? text : text.substring(0, maxTextLength);\n}\n\nexport class Avatar extends Component {\n render() {\n const {\n className,\n style,\n size = '',\n circle,\n rounded,\n background,\n foreColor,\n icon,\n text,\n code,\n maxTextLength = 2,\n src,\n hueDistance = 43,\n saturation = 0.4,\n lightness = 0.6,\n children,\n ...others\n } = this.props;\n\n const finalClass = ['avatar', className];\n const finalStyle = {...style, background, color: foreColor};\n\n let actualSize = 32;\n if (size) {\n if (typeof size === 'number') {\n finalStyle.width = `${size}px`;\n finalStyle.height = `${size}px`;\n finalStyle.fontSize = `${Math.max(12, Math.round(size / 2))}px`;\n actualSize = size;\n } else {\n finalClass.push(`size-${size}`);\n actualSize = ({xs: 20, sm: 24, lg: 48, xl: 80})[size];\n }\n }\n if (circle) {\n finalClass.push('circle');\n } else if (rounded) {\n if (typeof rounded === 'number') {\n finalStyle.borderRadius = `${rounded}px`;\n } else {\n finalClass.push(`rounded-${rounded}`);\n }\n }\n\n let content: ComponentChildren | undefined;\n if (src) {\n finalClass.push('has-img');\n content = {text};\n } else if (icon) {\n finalClass.push('has-icon');\n content = ;\n } else if (text?.length) {\n const displayText = getAvatarText(text, maxTextLength);\n finalClass.push('has-text', `has-text-${displayText.length}`);\n\n if (background === undefined) {\n const avatarCode = code ?? text;\n const hue = (typeof avatarCode === 'number' ? avatarCode : getUniqueCode(avatarCode)) * hueDistance % 360;\n finalStyle.background = `hsl(${hue},${saturation * 100}%,${lightness * 100}%)`;\n if (!foreColor) {\n const rgb = hslToRgb(hue, saturation, lightness);\n finalStyle.color = contrastColor(rgb);\n }\n } else if (!foreColor && background) {\n finalStyle.color = contrastColor(background);\n }\n let textStyle: JSX.CSSProperties | undefined;\n if (actualSize && actualSize < (14 * displayText.length)) {\n textStyle = {transform: `scale(${actualSize / (14 * displayText.length)})`, whiteSpace: 'nowrap'};\n }\n\n content =

    {displayText}
    ;\n }\n\n return (\n \n {content}\n {children}\n \n );\n }\n}\n","import {$, mergeProps, removeUndefinedProps} from '@zui/core';\nimport {Button} from '@zui/button/src/component';\nimport {CommonList} from '@zui/common-list/src/component';\n\nimport type {RenderableProps} from 'preact';\nimport type {ButtonProps} from '@zui/button';\nimport type {Item} from '@zui/common-list';\nimport type {BtnGroupOptions} from '../types';\n\nexport class BtnGroup extends CommonList {\n static NAME = 'btn-group';\n\n /**\n * Root element default tag name, used for DOM rendering.\n */\n static TAG = 'nav';\n\n static ItemComponents = {\n ...CommonList.ItemComponents,\n default: Button,\n };\n\n /**\n * Item default common props, used for rendering for all item types.\n */\n static defaultItemProps: Partial = {\n component: undefined,\n };\n\n protected _shareBtnProps?: Partial;\n\n protected _isBtnType({type}: Item): boolean {\n return type === 'item' || type === 'dropdown';\n }\n\n protected _getItem(props: RenderableProps, item: Item, index: number): false | Item {\n if (!item.type) {\n item = $.extend({type: (item.dropdown || item.items) ? 'dropdown' : 'item'}, item);\n }\n let itemProps = super._getItem(props, item, index);\n if (!itemProps) {\n return itemProps;\n }\n if (this._isBtnType(itemProps)) {\n itemProps = mergeProps({}, this._shareBtnProps, itemProps);\n }\n return itemProps;\n }\n\n protected _beforeRender(props: RenderableProps): void | RenderableProps | undefined {\n const {btnProps, btnType, size} = props;\n\n this._shareBtnProps = mergeProps({}, btnProps, removeUndefinedProps({btnType, size}));\n }\n}\n","import {classes, $, mergeProps} from '@zui/core';\nimport {BtnGroup} from '@zui/btn-group/src/component/btn-group';\n\nimport type {Item} from '@zui/common-list';\nimport type {ToolbarOptions, ToolbarSetting} from '../types';\nimport type {ClassNameLike} from '@zui/core/src/helpers';\nimport type {Attributes, RenderableProps} from 'preact';\n\nexport class Toolbar extends BtnGroup {\n static NAME = 'toolbar';\n\n static defaultProps: Partial = {\n btnProps: {\n btnType: 'ghost',\n },\n };\n\n static ItemComponents = {\n ...BtnGroup.ItemComponents,\n btnGroup: BtnGroup,\n 'btn-group': BtnGroup,\n };\n\n protected _getProps(props: RenderableProps): Record {\n const {gap} = props;\n const propsMap = super._getProps(props);\n if (gap) {\n if (typeof gap === 'number') {\n propsMap.className = classes(propsMap.className as ClassNameLike, `gap-${gap}`);\n } else {\n propsMap.style = $.extend(propsMap.style || {}, {gap: gap});\n }\n }\n return propsMap;\n }\n\n protected _getItem(props: RenderableProps, item: Item, index: number): false | Item {\n const itemProps = super._getItem(props, item, index);\n if (!itemProps) {\n return itemProps;\n }\n const {type} = itemProps;\n const isBtnGroup = type === 'btn-group' || type === 'btnGroup';\n if (isBtnGroup) {\n itemProps.btnProps = mergeProps({}, this._shareBtnProps, itemProps.btnProps);\n }\n if ((isBtnGroup || type === 'dropdown') && !itemProps.relativeTarget) {\n itemProps.relativeTarget = props.relativeTarget;\n }\n return itemProps;\n }\n\n static render(this: unknown, setting: ToolbarSetting | undefined, args: T, defaultProps?: Partial & Attributes, thisObject?: unknown) {\n let toolbarOptions = typeof setting === 'function' ? setting.call(thisObject ?? this, ...args) : setting;\n if (!toolbarOptions) {\n return;\n }\n if (Array.isArray(toolbarOptions)) {\n toolbarOptions = {\n items: toolbarOptions,\n };\n }\n if (defaultProps) {\n toolbarOptions = mergeProps(defaultProps as Record, toolbarOptions);\n }\n return ;\n }\n}\n","import {CustomContent, HElement} from '@zui/core';\n\nimport type {ClassNameLike} from '@zui/core';\nimport type {ComponentChildren, RenderableProps} from 'preact';\nimport type {CheckboxProps, CheckboxState} from '../types';\n\nexport class Checkbox

    extends HElement {\n protected _controlled: boolean;\n\n constructor(props: P) {\n super(props);\n this.state = {\n checked: props.checked ?? props.defaultChecked ?? false,\n };\n this._controlled = props.checked !== undefined;\n }\n\n get checked() {\n return this._controlled ? this.props.checked : this.state.checked;\n }\n\n protected _getClassName(props: RenderableProps

    ): ClassNameLike {\n const {disabled, type = 'checkbox'} = props;\n const {checked} = this;\n return [props.className, type === 'switch' ? type : `${type}-primary`, {\n disabled,\n checked: checked === true,\n indeterminate: checked === 'indeterminate',\n }];\n }\n\n protected _handleChange = (event: Event) => {\n const {onChange} = this.props;\n const checked = (event.target as HTMLInputElement).indeterminate ? 'indeterminate' : (event.target as HTMLInputElement).checked;\n if (onChange) {\n onChange.call(this, event, checked);\n }\n if (!this._controlled) {\n this.setState({checked});\n }\n };\n\n protected _getChildren(props: RenderableProps

    ): ComponentChildren {\n const {name, type, value, id, label} = props;\n const {checked} = this;\n return [\n name ? (\n \n ) : null,\n (),\n ];\n }\n}\n","import {RadioProps} from '../types';\nimport {Checkbox} from './checkbox';\n\nexport class Radio

    extends Checkbox

    {\n static defaultProps: Partial = {\n type: 'radio',\n };\n}\n","import {SwitchProps} from '../types';\nimport {Checkbox} from './checkbox';\n\nexport class Switch

    extends Checkbox

    {\n static defaultProps: Partial = {\n type: 'switch',\n };\n}\n","import {toChildArray} from 'preact';\nimport {CustomContent, HElement, Icon, classes, mergeProps} from '@zui/core';\nimport {Avatar} from '@zui/avatar/src/component';\nimport {Toolbar} from '@zui/toolbar/src/component';\nimport {Checkbox} from '@zui/checkbox/src/component';\n\nimport type {ComponentChild, ComponentChildren, ComponentType, JSX, RenderableProps} from 'preact';\nimport type {ListitemProps} from '../types';\n\nexport class Listitem

    extends HElement {\n protected _renderLeading(props: RenderableProps

    ): ComponentChild[] {\n const {\n icon,\n avatar,\n toggleIcon,\n leading,\n leadingClass,\n checked,\n checkbox,\n multiline,\n } = props;\n const contents: ComponentChild[] = [];\n if (toggleIcon) {\n contents.push();\n }\n if (checked !== undefined) {\n contents.push();\n }\n if (icon) {\n contents.push();\n }\n if (avatar) {\n const avatarProps = typeof avatar === 'function' ? avatar.call(this, props) : avatar;\n if (avatarProps) {\n avatarProps.className = classes('item-avatar', avatarProps.className);\n contents.push();\n }\n }\n const customLeading = leading ? : null;\n if (customLeading) {\n contents.push(customLeading);\n }\n if (multiline) {\n return contents.length ? [\n

    {contents}
    ,\n ] : [];\n }\n return contents;\n }\n\n protected _renderContent(props: RenderableProps

    , linkRendered?: boolean): ComponentChild[] {\n const {\n textClass,\n titleClass,\n titleAttrs,\n subtitle,\n subtitleClass,\n url,\n target,\n content,\n contentClass,\n contentAttrs,\n } = props;\n const titleAsLink = url && !linkRendered;\n const TitleComponent = titleAsLink ? 'a' : 'div';\n let {title, text} = props;\n if (title === undefined) {\n title = text;\n text = null;\n }\n return [\n

    \n {title ? : null}\n {subtitle ?
    : null}\n {text ?
    {text}
    : null}\n {content ? : null}\n
    ,\n ];\n }\n\n protected _renderTrailing(props: RenderableProps

    ): ComponentChild[] {\n const {\n multiline,\n trailing,\n trailingClass,\n trailingIcon,\n actions,\n } = props;\n const contents: ComponentChild[] = [];\n if (trailingIcon) {\n contents.push();\n }\n if (actions) {\n contents.push(Toolbar.render(actions, [props], {key: 'actions', relativeTarget: props, size: 'sm'}, this));\n }\n const customTrailing = trailing ? : null;\n if (customTrailing) {\n contents.push(customTrailing);\n }\n if (multiline) {\n return contents.length ? [\n

    {contents}{customTrailing}
    ,\n ] : [];\n }\n return contents;\n }\n\n protected _render(props: RenderableProps

    , extraAttrs?: Record): ComponentChild {\n const {\n innerComponent,\n innerClass,\n innerAttrs,\n url,\n actions,\n target,\n active,\n disabled,\n divider,\n checked,\n multiline,\n title,\n subtitle,\n hint,\n hover,\n } = props;\n const ComponentName = innerComponent || ((url && !actions) ? 'a' : 'div');\n const asLink = ComponentName === 'a';\n const attrs = mergeProps({\n key: 'item',\n title: hint,\n className: classes('listitem', innerClass, {\n active,\n disabled,\n 'has-divider': divider,\n 'has-hover state': hover,\n checked,\n multiline: multiline ?? !!(title && subtitle),\n state: asLink,\n }),\n }, asLink ? {href: url, target} : null, extraAttrs, innerAttrs);\n return (\n \n {this._renderLeading(props)}\n {this._renderContent(props, asLink)}\n {this._renderTrailing(props)}\n \n );\n }\n\n protected _onRender(component: ComponentType | keyof JSX.IntrinsicElements, componentProps: Record, children: ComponentChildren, _props: RenderableProps

    ): void | [component: ComponentType | keyof JSX.IntrinsicElements, componentProps: Record, children: ComponentChildren] {\n const innerAttrs = Object.keys(componentProps).reduce>((attrs, key) => {\n if (key.startsWith('data-')) {\n attrs[key] = componentProps[key];\n delete componentProps[key];\n }\n return attrs;\n }, {});\n return [component, componentProps, [this._render(_props, innerAttrs), ...toChildArray(children)]];\n }\n}\n","import {$, HElement, classes, fetchData, mergeProps, removeUndefinedProps} from '@zui/core';\nimport {CommonList} from '@zui/common-list/src/component';\nimport {Listitem} from './listitem';\n\nimport type {ComponentChild, ComponentChildren, RenderableProps} from 'preact';\nimport type {ClassNameLike, CustomContentType} from '@zui/core';\nimport type {Item, ItemKey} from '@zui/common-list';\nimport type {CheckedType} from '@zui/checkbox';\nimport type {ListProps, ListState, ListItemsSetting, ListItemsFetcher} from '../types';\n\nexport class List

    extends CommonList {\n static ItemComponents: typeof CommonList.ItemComponents = {\n ...CommonList.ItemComponents,\n default: HElement,\n item: Listitem,\n heading: Listitem,\n };\n\n static NAME = 'list';\n\n protected _loadedSetting?: ListItemsSetting;\n\n protected declare _hasIcons: boolean;\n\n protected declare _hasCheckbox: boolean;\n\n constructor(props: P) {\n super(props);\n this.state = {\n checked: {},\n } as S;\n }\n\n componentDidMount() {\n this._afterRender(true);\n this.tryLoad();\n }\n\n componentDidUpdate(): void {\n this._afterRender(false);\n this.tryLoad();\n }\n\n componentWillUnmount(): void {\n this.props.beforeDestroy?.call(this);\n }\n\n setItems(items?: Item[], error?: Error) {\n const {onLoadFail} = this.props;\n this.setState({\n loading: false,\n items: items || [],\n loadFailed: error ? (typeof onLoadFail === 'function' ? (onLoadFail as (error: Error) => CustomContentType | undefined).call(this, error as Error) : onLoadFail) || String(error) : undefined,\n });\n }\n\n load(): void {\n const {items, onLoad} = this.props;\n this._loadedSetting = items;\n this.setState({loading: true, items: []}, async () => {\n try {\n const newItems = await fetchData(items as ListItemsFetcher, [this], {throws: true});\n this.setItems(onLoad?.call(this, newItems) || newItems);\n } catch (error) {\n this.setItems(undefined, error as Error);\n }\n });\n }\n\n tryLoad() {\n const {loading} = this.state;\n const {items} = this.props;\n if (loading || !items || Array.isArray(items) || items === this._loadedSetting) {\n return false;\n }\n this.load();\n return true;\n }\n\n isChecked(key: ItemKey, index?: number, defaultChecked: CheckedType = false): CheckedType {\n const item = (typeof index === 'number' ? this._items[index] : this.getItem(key)) || {};\n return this.state.checked[key] ?? item.checked ?? defaultChecked;\n }\n\n isAllChecked(): boolean {\n return this._renderedItems.every(({key}, index) => this.isChecked(key!, index) === true);\n }\n\n toggleAllChecked(checked?: boolean): void {\n if (checked === undefined) {\n checked = !this.isAllChecked();\n }\n this.toggleChecked(this._renderedItems.map(x => x.key!), checked);\n }\n\n toggleChecked(keyOrChange: ItemKey | ItemKey[] | Record, checked?: boolean): void {\n let change: Record;\n if (Array.isArray(keyOrChange)) {\n if (!keyOrChange.length) {\n return;\n }\n if (checked === undefined) {\n checked = !this.isChecked(keyOrChange[0]);\n }\n change = keyOrChange.reduce>((map, key) => {\n map[key] = checked!;\n return map;\n }, {});\n } else if (typeof keyOrChange === 'object') {\n change = keyOrChange;\n } else {\n const isChecked = this.isChecked(keyOrChange);\n if (checked === undefined) {\n checked = !isChecked;\n }\n change = {[keyOrChange]: checked!};\n }\n if (!Object.keys(change).length) {\n return;\n }\n\n this.setState(prevState => ({\n checked: {\n ...prevState.checked,\n ...change,\n },\n }), () => {\n const checkState = this.state.checked;\n this.props.onCheck?.call(this, change, Object.keys(checkState).filter(x => checkState[x] === true));\n });\n }\n\n getChecks() {\n return this._renderedItems.reduce((checks, {key}, index) => {\n if (key !== undefined && this.isChecked(key, index) === true) {\n checks.push(key);\n }\n return checks;\n }, []);\n }\n\n protected _afterRender(firstRender: boolean) {\n this.props.afterRender?.call(this, firstRender);\n }\n\n protected _getItems(props: RenderableProps

    ): Item[] {\n const {items} = props;\n const {items: stateItems} = this.state;\n return stateItems || (Array.isArray(items) ? items : []);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _getRenderedItem(props: RenderableProps

    , renderedItem: Item, index: number): Item {\n const {divider, hover, multiline} = props;\n renderedItem = mergeProps({}, removeUndefinedProps({\n divider,\n hover,\n multiline,\n }), renderedItem);\n\n const {itemName, name} = this;\n renderedItem.innerClass = [itemName ? `${itemName}-inner${name ? ` ${name}-${renderedItem.type}-inner` : ''}` : '', renderedItem.innerClass];\n\n if (renderedItem.type === 'item') {\n const {checkbox} = props;\n if (checkbox) {\n renderedItem.checked = this.isChecked(renderedItem.key!, index, renderedItem.checked as CheckedType);\n if (typeof checkbox === 'object') {\n renderedItem.checkbox = renderedItem.checkbox ? $.extend({}, checkbox, renderedItem.checkbox) : checkbox;\n }\n if (props.activeOnChecked && renderedItem.checked) {\n renderedItem.active = true;\n }\n }\n }\n\n if (renderedItem.icon) {\n this._hasIcons = true;\n }\n if (renderedItem.checked !== undefined) {\n this._hasCheckbox = true;\n }\n\n return renderedItem;\n }\n\n protected _getItem(props: RenderableProps

    , item: Item, index: number): Item | false {\n const renderedItem = super._getItem(props, item, index);\n if (!renderedItem) {\n return renderedItem;\n }\n return this._getRenderedItem(props, renderedItem, index);\n }\n\n protected _renderItem(props: RenderableProps

    , item: Item, index: number): ComponentChildren {\n if (item.type === 'item' && this._hasIcons && item.icon === undefined) {\n item.icon = 'EMPTY';\n }\n return super._renderItem(props, item, index);\n }\n\n protected _handleClick(event: MouseEvent) {\n const info = super._handleClick(event);\n let {checkOnClick} = this.props;\n if (checkOnClick === 'any') {\n checkOnClick = '.item-checkbox,.item-content,.item-icon';\n } else if (checkOnClick === true) {\n checkOnClick = '.item-checkbox';\n }\n if (checkOnClick && info && (event.target as HTMLElement).closest(checkOnClick)) {\n this.toggleChecked(info.key);\n event.stopPropagation();\n return;\n }\n return info;\n }\n\n protected _getClassName(props: RenderableProps

    ): ClassNameLike {\n const {loading, loadFailed} = this.state;\n return [super._getClassName(props), loading ? 'loading' : (loadFailed ? 'is-load-failed' : '')];\n }\n\n protected _getProps(props: RenderableProps

    ): Record {\n const {className, ...others} = super._getProps(props);\n return {\n ...others,\n className: classes(className as ClassNameLike, this._hasIcons ? 'has-icons' : '', this._hasCheckbox ? 'has-checkbox' : ''),\n };\n }\n\n protected _getChildren(props: RenderableProps

    ): ComponentChildren {\n const children = super._getChildren(props) as ComponentChild[];\n const {loadFailed} = this.state;\n if (loadFailed) {\n children.push(loadFailed);\n }\n return children;\n }\n}\n","/** Store type. */\nexport type StoreType = 'local' | 'session';\n\nconst STR_PREFIX = '```ZUI_STR\\n';\n\n/**\n * Store for using localStorage and sessionStorage.\n */\nexport class Store {\n protected _type: StoreType;\n\n protected _name: string;\n\n protected _id: string;\n\n protected _storage: Storage;\n\n protected _altStorage?: Store;\n\n /**\n * Create new store instance.\n * @param id Store profile ID.\n * @param type Store type.\n */\n constructor(id: string = '', type: StoreType = 'local') {\n this._type = type;\n this._id = id;\n this._name = `ZUI_STORE:${this._id}`;\n this._storage = type === 'local' ? localStorage : sessionStorage;\n }\n\n /**\n * Get store type.\n */\n get type(): StoreType {\n return this._type;\n }\n\n /**\n * Get session type store instance.\n */\n get session(): Store {\n if (this.type === 'session') {\n return this;\n }\n if (!this._altStorage) {\n this._altStorage = new Store(this._id, 'session');\n }\n return this._altStorage;\n }\n\n protected _getKey(key: string): string {\n return `${this._name}:${key}`;\n }\n\n /**\n * Switch store profile.\n *\n * @param id Store profile ID.\n */\n switch(id: string) {\n this._id = id;\n this._name = `ZUI_STORE:${this._id}`;\n }\n\n /**\n * Get value from store.\n *\n * @param key Key to get\n * @returns Value of key or undefined if key is not found\n */\n get(key: string): T | undefined;\n\n /**\n * Get value from store, if key is not found, return defaultValue.\n *\n * @param key Key to get.\n * @param defaultValue Default value to return if key is not found.\n */\n get(key: string, defaultValue: T): T;\n\n /**\n * Get value from store.\n *\n * @param key Key to get.\n * @param defaultValue Default value to return if key is not found.\n * @returns Value of key or defaultValue if key is not found.\n */\n get(key: string, defaultValue?: T): T | undefined {\n const value = this._storage.getItem(this._getKey(key));\n if (typeof value === 'string') {\n if (value.startsWith(STR_PREFIX)) {\n return value.substring(STR_PREFIX.length) as T;\n }\n try {\n return JSON.parse(value);\n // eslint-disable-next-line no-empty\n } catch (_error) {}\n }\n return (value as T) ?? defaultValue;\n }\n\n /**\n * Set key-value pair in store.\n *\n * @param key Key to set.\n * @param value Value to set.\n */\n set(key: string, value: unknown): void {\n if (value === undefined || value === null) {\n return this.remove(key);\n }\n this._storage.setItem(this._getKey(key), typeof value === 'string' ? `${STR_PREFIX}${value}` : JSON.stringify(value));\n }\n\n /**\n * Remove key-value pair from store.\n *\n * @param key Key to remove.\n */\n remove(key: string): void {\n this._storage.removeItem(this._getKey(key));\n }\n\n /**\n * Iterate all key-value pairs in store.\n *\n * @param callback Callback function to call for each key-value pair in the store.\n */\n each(callback: (name: string, value: unknown) => void): void {\n for (let i = 0; i < this._storage.length; i++) {\n const key = this._storage.key(i);\n if (key?.startsWith(this._name)) {\n const value = this._storage.getItem(key);\n if (typeof value === 'string') {\n callback(key.substring(this._name.length + 1), JSON.parse(value));\n }\n }\n }\n }\n\n /**\n * Get all key values in store.\n *\n * @returns All key-value pairs in the store.\n */\n getAll(): Record {\n const result: Record = {};\n this.each((key, value) => {\n result[key] = value;\n });\n return result;\n }\n}\n","import {Store, StoreType} from './store';\n\nexport type {Store} from './store';\n\nexport const store = new Store('DEFAULT');\n\nfunction createStore(name?: string, type: StoreType = 'local') {\n return new Store(name, type);\n}\n\nObject.assign(store, {create: createStore});\n","import {Icon, classes, mergeProps, $} from '@zui/core';\nimport {store} from '@zui/store';\nimport {List} from './list';\nimport '@zui/css-icons/src/icons/caret.css';\n\nimport type {ComponentChild, ComponentChildren, RenderableProps} from 'preact';\nimport type {ClassNameLike} from '@zui/core';\nimport type {Item, ItemKey} from '@zui/common-list';\nimport type {CheckedType} from '@zui/checkbox';\nimport type {ListItemsSetting, NestedItem, NestedListProps, NestedListState} from '../types';\n\ntype MouseEventInfo = {\n index: number;\n item: NestedItem;\n renderedItem: NestedItem;\n element: HTMLElement;\n event: MouseEvent;\n key: ItemKey;\n parentKey?: ItemKey;\n hover?: boolean;\n keyPath: string;\n};\n\ntype ItemInfo = {\n key: string;\n level: number;\n keyPath: string;\n parentKey?: string;\n parent?: ItemInfo;\n children: ItemInfo[];\n data: Item;\n};\n\nfunction forEachChild(item: ItemInfo, callback: (child: ItemInfo) => void) {\n const {children} = item;\n if (!children.length) {\n return;\n }\n children.forEach(child => {\n callback(child);\n forEachChild(child, callback);\n });\n}\n\nfunction forEachParent(item: ItemInfo, callback: (parent: ItemInfo) => void) {\n let parent = item.parent;\n while (parent) {\n callback(parent);\n parent = parent.parent;\n }\n}\n\nfunction parentKeys(keyPath: string) {\n return keyPath.split(':').reduce((keys, item, index) => {\n keys.push(index ? keys[index - 1] + ':' + item : item);\n return keys;\n }, []);\n}\n\nfunction initItemMap(items: Item[], itemKey: string | undefined, map: Map = new Map(), level = 0, parent?: ItemInfo) {\n items.forEach((item, index) => {\n const key = String((itemKey ? item[itemKey] : item.key) ?? (item.key ?? index));\n const keyPath = parent ? `${parent.keyPath}:${key}` : key;\n const itemInfo = {\n key,\n level,\n keyPath,\n parentKey: parent?.keyPath,\n parent: parent,\n data: item,\n children: [],\n };\n if (parent) {\n parent.children.push(itemInfo);\n }\n map.set(keyPath, itemInfo);\n if (Array.isArray(item.items)) {\n initItemMap(item.items as Item[], itemKey, map, level + 1, itemInfo);\n }\n });\n return map;\n}\n\nexport class NestedList

    extends List {\n static defaultProps: Partial = {\n defaultNestedShow: false,\n level: 0,\n indent: 20,\n };\n\n static inheritNestedProps = ['component', 'name', 'itemName', 'itemKey', 'indent', 'hover', 'divider', 'multiline', 'toggleIcons', 'nestedToggle', 'itemRender', 'beforeRenderItem', 'onToggle', 'checkbox', 'getItem', 'checkOnClick', 'activeOnChecked', 'checkedState', 'onClickItem'];\n\n protected declare _hasNestedItems: boolean;\n\n protected declare _needHandleHover: boolean;\n\n protected declare _storeID: string;\n\n protected declare _renderedItemMap: Map;\n\n protected declare _itemMap?: Map;\n\n protected declare _needInitChecks?: boolean;\n\n constructor(props: P) {\n super(props);\n const {defaultNestedShow, preserve, nestedShow} = props;\n $.extend(\n this.state,\n typeof defaultNestedShow === 'boolean' ? {defaultShow: defaultNestedShow, nestedShow: {}} : {nestedShow: defaultNestedShow || {}},\n nestedShow !== undefined ? {nestedShow} : null,\n );\n if (preserve && nestedShow === undefined) {\n this._storeID = `${this.constructor.NAME}:${preserve}:state`;\n const storeState = store.get(this._storeID);\n if (storeState) {\n $.extend(this.state, storeState);\n }\n }\n\n if (!props.level) {\n const nestedState = this.state.nestedShow;\n if (nestedState) {\n Object.keys(nestedState).forEach(key => {\n if (!nestedState[key]) {\n return;\n }\n parentKeys(key).forEach(parentKey => {\n nestedState[parentKey] = true;\n });\n });\n }\n this._needInitChecks = true;\n }\n\n this._renderedItemMap = new Map();\n this._handleHover = this._handleHover.bind(this);\n this._handleClick = this._handleClick.bind(this);\n this._beforeRenderNestedItem = this._beforeRenderNestedItem.bind(this);\n this._handleNestedToggle = this._handleNestedToggle.bind(this);\n this._handleNestedCheck = this._handleNestedCheck.bind(this);\n this._preserveState = this._preserveState.bind(this);\n }\n\n get isRoot() {\n return !this.props.level;\n }\n\n get nestedShow() {\n return this.props.nestedShow ?? this.state.nestedShow ?? false;\n }\n\n setItems(items?: Item[] | undefined, error?: Error | undefined): void {\n if (this.isRoot) {\n this._needInitChecks = true;\n }\n super.setItems(items, error);\n }\n\n getItemMap() {\n if (!this._itemMap) {\n this._itemMap = initItemMap(this._items, this.props.itemKey);\n }\n return this._itemMap;\n }\n\n getRenderedItem(keyPath: string): Item | undefined {\n return this._renderedItemMap.get(keyPath);\n }\n\n getItem(keyPath: string) {\n if (this._itemMap) {\n return this._itemMap.get(keyPath)?.data;\n }\n const renderedItem = this.getRenderedItem(keyPath);\n return renderedItem ? (renderedItem._item as Item) : super.getItem(keyPath);\n }\n\n isExpanded(keyPath: string) {\n const {nestedShow} = this;\n if (typeof nestedShow === 'boolean') {\n return nestedShow;\n }\n return !!(nestedShow[keyPath] ?? this.state.defaultShow);\n }\n\n toggle(keyPath: string, toggle?: boolean) {\n const isExpanded = this.isExpanded(keyPath);\n if (toggle === isExpanded) {\n return;\n }\n if (toggle === undefined) {\n toggle = !isExpanded;\n }\n const {nestedShow, onToggle} = this.props;\n if (onToggle && onToggle.call(this, keyPath, toggle) === false) {\n return;\n }\n if (nestedShow !== undefined) {\n return;\n }\n return this.setState(prevState => {\n const newNestedShow = {\n ...prevState.nestedShow,\n [keyPath]: toggle!,\n };\n return {\n nestedShow: toggle ? parentKeys(keyPath).reduce>((map, key) => {\n map[key] = toggle!;\n return map;\n }, newNestedShow) : newNestedShow,\n };\n }, this._preserveState);\n }\n\n toggleAll(show: boolean) {\n if (this.props.nestedShow !== undefined) {\n return;\n }\n return this.setState({nestedShow: {}, defaultShow: show}, this._preserveState);\n }\n\n getChecks() {\n return Array.from(this.getItemMap().values()).reduce((checks, {keyPath, data}) => {\n if ((this.state.checked[keyPath] === true || data.checked) === true) {\n checks.push(keyPath);\n }\n return checks;\n }, []);\n }\n\n isChecked(key: ItemKey, index?: number, defaultChecked: CheckedType = false): CheckedType {\n const item = (typeof index === 'number' ? this._items[index] : this.getItem(key)) || {};\n if (this.isRoot) {\n return this.state.checked[key] ?? (item.checked as CheckedType) ?? defaultChecked;\n }\n return this.props.checkedState![`${this.props.parentKey}:${key}`] ?? (item.checked as CheckedType) ?? defaultChecked;\n }\n\n toggleChecked(keyOrChange: ItemKey | ItemKey[] | Record, checked?: CheckedType): void {\n let change: Record;\n if (Array.isArray(keyOrChange)) {\n if (!keyOrChange.length) {\n return;\n }\n if (checked === undefined) {\n checked = !this.isChecked(keyOrChange[0]);\n }\n change = keyOrChange.reduce>((map, key) => {\n map[key] = checked!;\n return map;\n }, {});\n } else if (typeof keyOrChange === 'object') {\n change = keyOrChange;\n } else {\n if (checked === undefined) {\n checked = !this.isChecked(keyOrChange);\n }\n change = {[keyOrChange]: checked!};\n }\n if (!Object.keys(change).length) {\n return;\n }\n if (this.isRoot) {\n const map = this.getItemMap();\n this.setState(({checked: prevChecked}) => {\n const isChecked = (item: ItemInfo) => {\n return change[item.keyPath] ?? prevChecked[item.keyPath] ?? item.data.checked ?? false;\n };\n Object.keys(change).forEach(key => {\n checked = change[key];\n const item = map.get(key);\n if (!item) {\n return;\n }\n forEachChild(item, child => {\n if (isChecked(child) !== checked) {\n change[child.keyPath] = checked!;\n }\n });\n forEachParent(item, parent => {\n const {children} = parent;\n const checkedCount = children.reduce((count, child) => {\n if (isChecked(child)) {\n count++;\n }\n return count;\n }, 0);\n\n change[parent.keyPath] = checkedCount === children.length ? true : (checkedCount ? 'indeterminate' : false);\n });\n });\n return {\n checked: {\n ...prevChecked,\n ...change,\n },\n };\n }, () => {\n const checkState = this.state.checked;\n this.props.onCheck?.call(this, change, Object.keys(checkState).filter(x => checkState[x] === true));\n });\n } else {\n const {parentKey, onCheck} = this.props;\n const nestedChange = Object.keys(change).reduce>((map, key) => {\n map[`${parentKey !== undefined ? `${parentKey}:` : ''}${key}`] = change[key];\n return map;\n }, {});\n onCheck!.call(this, nestedChange, []);\n }\n }\n\n protected _afterRender(firstRender: boolean): void {\n super._afterRender(firstRender);\n if (this._needInitChecks) {\n const initChecks: Record = {};\n const itemMap = this.getItemMap();\n itemMap.forEach(item => {\n if (item.data.checked !== undefined) {\n initChecks[item.keyPath] = item.data.checked as CheckedType;\n }\n });\n this.toggleChecked(initChecks);\n this._needInitChecks = false;\n }\n }\n\n protected _preserveState() {\n if (this._storeID) {\n store.set(this._storeID, this.state);\n }\n }\n\n protected _getClassName(props: RenderableProps

    ): ClassNameLike {\n return [super._getClassName(props), 'is-nested', props.level ? 'is-nested-sub' : 'is-nested-root'];\n }\n\n protected _getNestedProps(props: RenderableProps

    , items: ListItemsSetting, item: NestedItem, expanded: boolean): NestedListProps {\n const {\n parentKey,\n level = 0,\n } = props;\n return mergeProps(((this.constructor as typeof NestedList).inheritNestedProps.reduce>((propMap, key) => {\n propMap[key] = props[key as keyof P];\n return propMap;\n }, {})), {\n level: level + 1,\n className: `is-nested-${expanded ? 'expanded' : 'collapsed'}`,\n items,\n parentKey: parentKey ? `${parentKey}:${item.key}` : item.key,\n nestedShow: this.nestedShow,\n defaultNestedShow: this.state.defaultShow,\n checkedState: props.checkedState || this.state.checked,\n onCheck: this.isRoot ? this._handleNestedCheck : props.onCheck,\n onToggle: this.isRoot ? this._handleNestedToggle : props.onToggle,\n beforeRenderItem: this.isRoot ? this._beforeRenderNestedItem : props.beforeRenderItem,\n }, item.listProps);\n }\n\n protected _renderNestedList(props: RenderableProps

    , items: ListItemsSetting, item: NestedItem, expanded: boolean): ComponentChildren {\n if (!expanded && !props.renderCollapsedList) {\n return;\n }\n const nestedListProps = this._getNestedProps(props, items, item, expanded);\n const NestedListComponent = this.constructor as typeof NestedList;\n return ;\n }\n\n protected _renderNestedToggle(props: RenderableProps

    , isExpanded: boolean | undefined): ComponentChild {\n let toggleIcon: ComponentChild;\n let toggleClass = '';\n const {toggleIcons = {}} = props;\n if (typeof isExpanded === 'boolean') {\n toggleIcon = isExpanded ? (toggleIcons.expanded || ) : (toggleIcons.collapsed || );\n toggleClass = `state is-${isExpanded ? 'expanded' : 'collapsed'}`;\n } else {\n toggleIcon = ;\n toggleClass = 'is-empty';\n }\n return {toggleIcon};\n }\n\n protected _getItems(props: RenderableProps

    ): Item[] {\n const items = super._getItems(props);\n if (this.isRoot && items !== this._items) {\n this._itemMap = undefined;\n }\n return items;\n }\n\n protected _getItem(props: RenderableProps

    , item: NestedItem, index: number): NestedItem | false {\n const nestedItem = super._getItem(props, item, index) ?? item;\n if (!nestedItem) {\n return nestedItem;\n }\n const {parentKey} = props;\n const key = nestedItem.key!;\n const keyPath = `${parentKey !== undefined ? `${parentKey}:` : ''}${key}`;\n if (nestedItem.items) {\n const expanded = nestedItem.expanded ?? this.isExpanded(keyPath);\n mergeProps(nestedItem, {\n expanded: expanded,\n className: ['is-nested', `is-nested-${expanded ? 'show' : 'hide'}`],\n });\n this._hasNestedItems = true;\n }\n return mergeProps(nestedItem, {\n _level: props.level,\n _keyPath: keyPath,\n parentKey,\n });\n }\n\n protected _beforeRenderNestedItem(item: NestedItem): NestedItem | false {\n this._renderedItemMap.set(item._keyPath as string, item);\n return item;\n }\n\n protected _renderItem(props: RenderableProps

    , renderedItem: NestedItem, index: number): ComponentChildren {\n if (this._hasNestedItems && renderedItem.type === 'item' && renderedItem.toggleIcon === undefined) {\n renderedItem.toggleIcon = this._renderNestedToggle(props, renderedItem.expanded as boolean | undefined);\n }\n const nestedListContent = renderedItem.items ? this._renderNestedList(props, renderedItem.items, renderedItem, renderedItem.expanded as boolean) : null;\n renderedItem = mergeProps(renderedItem, {\n 'z-parent': renderedItem.parentKey,\n 'z-key-path': renderedItem._keyPath,\n }, this._needHandleHover ? {\n onMouseEnter: this._handleHover,\n onMouseLeave: this._handleHover,\n } : null, nestedListContent ? {children: nestedListContent} : null);\n this._renderedItemMap.set(renderedItem._keyPath as string, renderedItem);\n return super._renderItem(props, renderedItem, index);\n }\n\n protected _getItemFromEvent(event: MouseEvent): MouseEventInfo | undefined {\n const info = super._getItemFromEvent(event) as MouseEventInfo;\n if (!info) {\n return;\n }\n if (event.type === 'mouseenter' || event.type === 'mouseleave') {\n info.hover = event.type === 'mouseenter';\n }\n const {parentKey} = this.props;\n return {...info, parentKey, keyPath: `${parentKey !== undefined ? `${parentKey}:` : ''}${info.key}`};\n }\n\n protected _toggleFromEvent(info: MouseEventInfo) {\n const {item, hover, event, keyPath} = info;\n const {nestedTrigger, nestedToggle} = this.props;\n const target = event.target as HTMLElement;\n if (!item.items || event.defaultPrevented || (nestedTrigger === 'hover' && hover === undefined) || (nestedTrigger === 'click' && event.type !== 'click') || target.closest('.not-nested-toggle') || (nestedToggle && !target.closest(nestedToggle)) || (!nestedToggle && target.closest('a,.btn,.item-checkbox') && !target.closest('.nested-toggle-icon,.item-icon'))) {\n return info;\n }\n const toggle = typeof hover === 'boolean' ? hover : undefined;\n this.toggle(keyPath, toggle);\n }\n\n protected _handleNestedToggle(key: ItemKey, toggle: boolean) {\n this.toggle(key, toggle);\n }\n\n protected _handleClick(event: MouseEvent) {\n const info = super._handleClick(event);\n if (info) {\n return this._toggleFromEvent(info as MouseEventInfo);\n }\n return info;\n }\n\n protected _handleHover(event: MouseEvent) {\n const info = this._getItemFromEvent(event);\n if (!info) {\n return;\n }\n this.props.onHoverItem?.call(this, info as {hover: boolean, item: NestedItem, index: number, event: MouseEvent});\n if (this.props.nestedTrigger === 'hover') {\n this._toggleFromEvent(info);\n }\n }\n\n protected _handleNestedCheck(change: Record) {\n this.toggleChecked(change);\n }\n\n protected _getProps(props: RenderableProps

    ): Record {\n const {level = 0, indent = 20, parentKey} = props;\n const finalProps = mergeProps(super._getProps(props), {\n 'z-level': level,\n 'z-parent-key': parentKey,\n style: {'--list-nested-indent': `${level * indent}px`, '--list-indent': `${indent}px`},\n className: this._hasNestedItems ? 'has-nested-items' : 'no-nested-items',\n });\n finalProps.className = classes(finalProps.className as ClassNameLike);\n return finalProps;\n }\n\n protected _beforeRender(props: RenderableProps

    ): void | RenderableProps

    | undefined {\n this._renderedItemMap.clear();\n this._hasIcons = false;\n this._hasNestedItems = !this.isRoot;\n this._needHandleHover = !!(props.onHoverItem || props.nestedTrigger === 'hover');\n return super._beforeRender(props);\n }\n}\n","import {ComponentFromReact} from '@zui/core';\nimport {List as ListReact} from '../component';\nimport type {ListProps} from '../types';\n\nexport class List extends ComponentFromReact {\n static NAME = 'List';\n\n static Component = ListReact;\n\n static replace = ListReact.TAG;\n}\n","import {ComponentFromReact} from '@zui/core';\nimport {NestedList as NestedListReact} from '../component';\nimport type {NestedListProps} from '../types';\n\nexport class NestedList extends ComponentFromReact {\n static NAME = 'NestedList';\n\n static Component = NestedListReact;\n\n static replace = NestedListReact.TAG;\n}\n","import {classes} from '@zui/core';\nimport {NestedList, Listitem} from '@zui/list/src/component';\n\nimport type {RenderableProps} from 'preact';\nimport type {ClassNameLike} from '@zui/core';\nimport type {NestedListState} from '@zui/list';\nimport type {MenuOptions} from '../types';\n\nexport class Menu extends NestedList {\n static NAME = 'menu';\n\n static TAG = 'menu';\n\n static inheritNestedProps = [...NestedList.inheritNestedProps, 'compact'];\n\n static ItemComponents: typeof NestedList.ItemComponents = {\n ...NestedList.ItemComponents,\n item: [Listitem, {innerComponent: 'a'}],\n };\n\n protected _getClassName(props: RenderableProps): ClassNameLike {\n return classes(super._getClassName(props), this._hasNestedItems ? 'menu-nested' : '', props.className, props.popup ? 'popup' : '', props.compact ? 'compact' : '');\n }\n}\n","import {Component, createRef} from 'preact';\nimport {classes, Icon, nextGid} from '@zui/core';\nimport '../style';\n\nimport type {ComponentChildren, RenderableProps} from 'preact';\nimport type {SearchBoxOptions, SearchBoxState} from '../types';\n\nexport class SearchBox extends Component {\n static defaultProps: Partial = {\n clearIcon: true,\n searchIcon: true,\n delay: 500,\n };\n\n protected _gid: string;\n\n protected _input = createRef();\n\n protected _timer = 0;\n\n constructor(props: SearchBoxOptions) {\n super(props);\n this.state = {focus: false, value: props.defaultValue || ''};\n this._gid = props.id || `search-box-${nextGid()}`;\n }\n\n get id() {\n return this._gid;\n }\n\n get input() {\n return this._input.current;\n }\n\n #handleClearBtnClick = (event: MouseEvent) => {\n const oldValue = this.state.value;\n event.stopPropagation();\n this.setState({value: ''}, () => {\n const {onChange, onClear} = this.props;\n onClear?.(event);\n this.focus();\n if (oldValue.trim() !== '') {\n onChange?.('', event);\n }\n });\n };\n\n #handleChange = (event: Event) => {\n const oldValue = this.state.value;\n const value = (event.target as HTMLInputElement).value;\n const {onChange} = this.props;\n this.setState({value}, () => {\n if (!onChange || oldValue === value) {\n return;\n }\n this.#clearTimer();\n this._timer = window.setTimeout(() => {\n onChange(value, event);\n this._timer = 0;\n }, this.props.delay || 0);\n });\n };\n\n #handleFocus = (event: FocusEvent) => {\n const focus = event.type === 'focus';\n this.setState({focus}, () => {\n const callback = focus ? this.props.onFocus : this.props.onBlur;\n callback?.(event);\n });\n };\n\n #clearTimer() {\n if (this._timer) {\n clearTimeout(this._timer);\n }\n this._timer = 0;\n }\n\n focus() {\n this.input?.focus();\n }\n\n componentWillUnmount(): void {\n this.#clearTimer();\n }\n\n render(props: RenderableProps, state: Readonly) {\n const {style, className, rootClass, rootStyle, readonly, disabled, circle, placeholder, mergeIcon, searchIcon, clearIcon, value: controlledValue} = props;\n const {focus, value} = state;\n const {id} = this;\n const finalValue = controlledValue ?? value;\n const empty = typeof finalValue !== 'string' || !finalValue.trim().length;\n let prefixView: ComponentChildren;\n let suffixView: ComponentChildren;\n let searchIconView: ComponentChildren;\n if (searchIcon) {\n searchIconView = searchIcon === true ? : ;\n }\n if (!mergeIcon && searchIcon) {\n prefixView = ;\n }\n if (clearIcon && !empty) {\n suffixView = (\n \n {clearIcon === true ? : }\n \n );\n } else if (mergeIcon && searchIcon) {\n suffixView = searchIconView;\n }\n if (suffixView) {\n suffixView = (\n \n );\n }\n\n return (\n

    \n {prefixView}\n \n {suffixView}\n
    \n );\n }\n}\n","import {$} from '@zui/core';\nimport {SearchBox} from '@zui/search-box/src/components';\nimport {Menu} from './menu';\n\nimport {toChildArray, type ComponentChild, type ComponentChildren, type RenderableProps} from 'preact';\nimport type {ClassNameLike} from '@zui/core';\nimport type {Item, ItemKey} from '@zui/common-list';\nimport type {ListItemsSetting, NestedItem, NestedListItem, NestedListProps} from '@zui/list';\nimport type {SearchBoxOptions} from '@zui/search-box';\nimport type {SearchMenuOptions, SearchMenuState} from '../types';\n\nexport class SearchMenu extends Menu {\n static inheritNestedProps = [...Menu.inheritNestedProps, 'isItemMatch', 'search', 'underlineKeys'];\n\n static defaultProps: Partial = {\n ...Menu.defaultProps,\n defaultNestedShow: true,\n };\n\n protected declare _searchKeys: string[];\n\n protected declare _matchedParents: Set;\n\n constructor(props: T) {\n super(props);\n (this.state as SearchMenuState).search = props.search ?? props.defaultSearch;\n this._searchKeys = (this.constructor as typeof SearchMenu).getSearchKeys(this.state.search);\n this._isNestedItemMatch = this._isNestedItemMatch.bind(this);\n }\n\n componentWillUpdate(nextProps: Readonly): void {\n if (this.isRoot) {\n if (nextProps.search !== undefined && nextProps.search !== this.props.search) {\n this._searchKeys = (this.constructor as typeof SearchMenu).getSearchKeys(nextProps.search);\n }\n }\n }\n\n componentDidMount(): void {\n super.componentDidMount();\n this._updateMatchedParents();\n }\n\n componentDidUpdate(): void {\n super.componentDidUpdate();\n this._updateMatchedParents();\n }\n\n isExpanded(keyPath: string): boolean {\n if (this.props.expandOnSearch && this._searchKeys.length) {\n return true;\n }\n return super.isExpanded(keyPath);\n }\n\n protected _updateMatchedParents(): void {\n if (!this.isRoot) {\n return;\n }\n $(this.element).find('.item.is-nested.is-not-match').filter((_, element) => this._matchedParents.has(element.getAttribute('z-key-path') || '')).addClass('has-match-child');\n }\n\n protected _handleSearchChange = (search: string) => {\n const searchKeys = (this.constructor as typeof SearchMenu).getSearchKeys(search);\n this._searchKeys = searchKeys;\n this.setState({search: searchKeys.join(' ')});\n };\n\n protected _isItemMatch(props: RenderableProps, item: NestedItem, index: number, parentKey: ItemKey | undefined) {\n const {isItemMatch} = props;\n const isMatch = isItemMatch ? isItemMatch.call(this, item, this._searchKeys, index, parentKey) : (this.constructor as typeof SearchMenu).isItemMatch(item, this._searchKeys, props.searchProps);\n if (this.isRoot && isMatch && parentKey !== undefined) {\n let key = '';\n String(parentKey).split(':').forEach(x => {\n key += `${key.length ? ':' : ''}${x}`;\n this._matchedParents.add(key);\n });\n }\n return isMatch;\n }\n\n protected _isNestedItemMatch(item: NestedItem, _searchKeys: string[], index: number, parentKey: ItemKey | undefined): boolean {\n return this._isItemMatch(this.props, item, index, parentKey);\n }\n\n protected _getNestedProps(props: RenderableProps, items: ListItemsSetting, item: NestedItem, expanded: boolean): NestedListProps {\n const nestedProps = super._getNestedProps(props, items, item, expanded) as SearchMenuOptions;\n if (this.isRoot) {\n nestedProps.isItemMatch = this._isNestedItemMatch;\n nestedProps.search = this._searchKeys.join(' ');\n }\n return nestedProps;\n }\n\n protected _getItem(props: RenderableProps, item: NestedItem, index: number): NestedItem | false {\n const finalItem = super._getItem(props, item, index);\n if (!finalItem) {\n return finalItem;\n }\n finalItem.hidden = !this._isItemMatch(props, item, index, props.parentKey);\n return finalItem;\n }\n\n\n protected _renderItem(props: RenderableProps, item: Item, index: number): ComponentChildren {\n item.className = [item.className, item.hidden ? 'is-not-match' : ''];\n if (props.underlineKeys && this._searchKeys.length) {\n ['text', 'title', 'subtitle', 'content'].forEach(key => {\n if (typeof item[key] === 'string') {\n item[key] = (this.constructor as typeof SearchMenu).underlineKeys(this._searchKeys, [item[key] as string]);\n }\n });\n }\n return super._renderItem(props, item, index);\n }\n\n protected _getChildren(props: RenderableProps): ComponentChildren {\n let children = super._getChildren(props);\n const {searchBox} = props;\n if (!searchBox || !this.isRoot) {\n return children;\n }\n children = toChildArray(children);\n const searchOptions: SearchBoxOptions = {\n onChange: this._handleSearchChange,\n };\n if (typeof searchBox === 'object') {\n $.extend(searchOptions, searchBox);\n }\n if (props.search !== undefined) {\n searchOptions.value = this._searchKeys.join(' ');\n searchOptions.disabled = true;\n }\n (children as ComponentChild[]).push();\n return children;\n }\n\n protected _getClassName(props: RenderableProps): ClassNameLike {\n const isSearchMode = this.isRoot && this._searchKeys.length;\n return [super._getClassName(props), 'search-menu', props.searchBox ? `search-menu-on-${props.searchPlacement || 'top'}` : '', isSearchMode ? 'is-search-mode' : '', isSearchMode && props.expandOnSearch ? 'no-toggle-on-search' : ''];\n }\n\n protected _beforeRender(props: RenderableProps): void | RenderableProps | undefined {\n if (this.isRoot) {\n this._matchedParents = new Set();\n }\n return super._beforeRender(props);\n }\n\n /**\n * Check whether item is matched.\n *\n * @param item Item to match.\n * @param searchKeys Search keys.\n * @returns Whether item is matched.\n */\n static isItemMatch(item: Item, searchKeys: string[], searchProps = ['keys', 'text', 'title', 'subtitle']) {\n if (!searchKeys.length) {\n return true;\n }\n return searchKeys.every(searchKey => searchProps.some(propName => {\n const propValue = item[propName];\n return typeof propValue === 'string' && propValue.length && propValue.toLowerCase().includes(searchKey);\n }));\n }\n\n /**\n * Convert search string to search keys.\n *\n * @param search Search string.\n * @returns Search keys array.\n */\n static getSearchKeys(search: string = ''): string[] {\n return $.unique((search).toLowerCase().split(' ').filter(x => x.length)) as string[];\n }\n\n static underlineKeys(searchKeys: string[], text: string[], className = 'is-match-keys'): ComponentChild[] {\n return searchKeys.reduce((result, key) => {\n return [...result].reduce((list, span) => {\n if (typeof span !== 'string') {\n list.push(span);\n return list;\n }\n const parts = span.toLowerCase().split(key);\n if (parts.length === 1) {\n list.push(span);\n return list;\n }\n let start = 0;\n parts.forEach((part, index) => {\n if (index) {\n list.push({span.substring(start, start + key.length)});\n start += key.length;\n }\n list.push(span.substring(start, start + part.length));\n start += part.length;\n });\n return list;\n }, []);\n }, text);\n }\n}\n","import {ComponentFromReact} from '@zui/core';\nimport {Menu as MenuReact} from '../component';\n\nimport type {MenuOptions} from '../types';\n\nexport class Menu extends ComponentFromReact> {\n static NAME = 'Menu';\n\n static Component = MenuReact;\n\n static replace = MenuReact.TAG;\n}\n","import {ComponentFromReact} from '@zui/core';\nimport {SearchMenu as MenuReact} from '../component';\n\nimport type {SearchMenuOptions} from '../types';\n\nexport class SearchMenu extends ComponentFromReact {\n static NAME = 'SearchMenu';\n\n static Component = MenuReact;\n\n static replace = MenuReact.TAG;\n}\n","import {isValidElement, ComponentChildren} from 'preact';\nimport {classes, CustomContent, Icon} from '@zui/core';\nimport {Button} from '@zui/button/src/component/button';\nimport type {ButtonProps} from '@zui/button';\nimport type {ToolbarOptions} from '@zui/toolbar';\nimport '@zui/css-icons/src/icons/close.css';\nimport {AlertOptions} from '../types';\nimport {Toolbar} from '@zui/toolbar/src/component';\n\nexport function Alert({\n className,\n style,\n actions,\n heading,\n content,\n contentClass,\n children,\n close,\n onClose,\n icon,\n iconClass,\n ...others\n}: AlertOptions) {\n let closeButton: ComponentChildren;\n if (close === true) {\n closeButton = ;\n } else if (isValidElement(close)) {\n closeButton = close;\n } else if (typeof close === 'object') {\n closeButton =