wok-ui-ext 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +75 -0
  3. package/README.md +75 -0
  4. package/dist/alert/index.d.ts +10 -0
  5. package/dist/alert/index.js +48 -0
  6. package/dist/alert/style.css +116 -0
  7. package/dist/avatar/index.d.ts +9 -0
  8. package/dist/avatar/index.js +30 -0
  9. package/dist/avatar/style.css +32 -0
  10. package/dist/badge/index.d.ts +32 -0
  11. package/dist/badge/index.js +61 -0
  12. package/dist/badge/style.css +68 -0
  13. package/dist/breadcrumb/index.d.ts +25 -0
  14. package/dist/breadcrumb/index.js +47 -0
  15. package/dist/breadcrumb/style.css +35 -0
  16. package/dist/button/index.d.ts +34 -0
  17. package/dist/button/index.js +57 -0
  18. package/dist/button/style.css +133 -0
  19. package/dist/card/index.d.ts +25 -0
  20. package/dist/card/index.js +29 -0
  21. package/dist/card/style.css +23 -0
  22. package/dist/collapse/index.d.ts +89 -0
  23. package/dist/collapse/index.js +213 -0
  24. package/dist/collapse/style.css +76 -0
  25. package/dist/context-menu/context-menu.d.ts +113 -0
  26. package/dist/context-menu/context-menu.js +150 -0
  27. package/dist/context-menu/index.d.ts +30 -0
  28. package/dist/context-menu/index.js +42 -0
  29. package/dist/context-menu/style.css +46 -0
  30. package/dist/date-picker/calendar-panel.d.ts +44 -0
  31. package/dist/date-picker/calendar-panel.js +180 -0
  32. package/dist/date-picker/date-picker.d.ts +29 -0
  33. package/dist/date-picker/date-picker.js +81 -0
  34. package/dist/date-picker/date-utils.d.ts +63 -0
  35. package/dist/date-picker/date-utils.js +130 -0
  36. package/dist/date-picker/index.d.ts +7 -0
  37. package/dist/date-picker/index.js +5 -0
  38. package/dist/date-picker/layer.d.ts +19 -0
  39. package/dist/date-picker/layer.js +36 -0
  40. package/dist/date-picker/range-picker.d.ts +30 -0
  41. package/dist/date-picker/range-picker.js +117 -0
  42. package/dist/date-picker/style.css +161 -0
  43. package/dist/description-list/index.d.ts +37 -0
  44. package/dist/description-list/index.js +145 -0
  45. package/dist/description-list/style.css +63 -0
  46. package/dist/divider/index.d.ts +29 -0
  47. package/dist/divider/index.js +29 -0
  48. package/dist/divider/style.css +50 -0
  49. package/dist/drawer/index.d.ts +51 -0
  50. package/dist/drawer/index.js +183 -0
  51. package/dist/drawer/style.css +100 -0
  52. package/dist/dropdown/index.d.ts +38 -0
  53. package/dist/dropdown/index.js +97 -0
  54. package/dist/dropdown/style.css +39 -0
  55. package/dist/empty/index.d.ts +11 -0
  56. package/dist/empty/index.js +20 -0
  57. package/dist/empty/style.css +19 -0
  58. package/dist/floating-layer/index.d.ts +109 -0
  59. package/dist/floating-layer/index.js +337 -0
  60. package/dist/floating-layer/style.css +5 -0
  61. package/dist/form/form-item/index.d.ts +26 -0
  62. package/dist/form/form-item/index.js +21 -0
  63. package/dist/form/form-item/style.css +33 -0
  64. package/dist/form/form-modal/index.d.ts +18 -0
  65. package/dist/form/form-modal/index.js +38 -0
  66. package/dist/form/form.d.ts +21 -0
  67. package/dist/form/form.js +28 -0
  68. package/dist/form/index.d.ts +4 -0
  69. package/dist/form/index.js +4 -0
  70. package/dist/form/select/index.d.ts +48 -0
  71. package/dist/form/select/index.js +94 -0
  72. package/dist/form/select/style.css +29 -0
  73. package/dist/global.css +71 -0
  74. package/dist/i18n/de-DE.d.ts +2 -0
  75. package/dist/i18n/de-DE.js +36 -0
  76. package/dist/i18n/en-US.d.ts +2 -0
  77. package/dist/i18n/en-US.js +36 -0
  78. package/dist/i18n/es-ES.d.ts +2 -0
  79. package/dist/i18n/es-ES.js +36 -0
  80. package/dist/i18n/fr-FR.d.ts +2 -0
  81. package/dist/i18n/fr-FR.js +36 -0
  82. package/dist/i18n/index.d.ts +12 -0
  83. package/dist/i18n/index.js +39 -0
  84. package/dist/i18n/ja-JP.d.ts +2 -0
  85. package/dist/i18n/ja-JP.js +36 -0
  86. package/dist/i18n/ko-KR.d.ts +2 -0
  87. package/dist/i18n/ko-KR.js +36 -0
  88. package/dist/i18n/messages.d.ts +40 -0
  89. package/dist/i18n/messages.js +1 -0
  90. package/dist/i18n/wok-ui/de-DE.d.ts +2 -0
  91. package/dist/i18n/wok-ui/de-DE.js +20 -0
  92. package/dist/i18n/wok-ui/es-ES.d.ts +2 -0
  93. package/dist/i18n/wok-ui/es-ES.js +20 -0
  94. package/dist/i18n/wok-ui/fr-FR.d.ts +2 -0
  95. package/dist/i18n/wok-ui/fr-FR.js +20 -0
  96. package/dist/i18n/wok-ui/ja-JP.d.ts +2 -0
  97. package/dist/i18n/wok-ui/ja-JP.js +20 -0
  98. package/dist/i18n/wok-ui/ko-KR.d.ts +2 -0
  99. package/dist/i18n/wok-ui/ko-KR.js +20 -0
  100. package/dist/i18n/wok-ui/zh-TW.d.ts +2 -0
  101. package/dist/i18n/wok-ui/zh-TW.js +20 -0
  102. package/dist/i18n/zh-CN.d.ts +2 -0
  103. package/dist/i18n/zh-CN.js +36 -0
  104. package/dist/i18n/zh-TW.d.ts +2 -0
  105. package/dist/i18n/zh-TW.js +36 -0
  106. package/dist/icons.d.ts +88 -0
  107. package/dist/icons.js +176 -0
  108. package/dist/image/index.d.ts +38 -0
  109. package/dist/image/index.js +97 -0
  110. package/dist/image/style.css +72 -0
  111. package/dist/image-preview/index.d.ts +26 -0
  112. package/dist/image-preview/index.js +134 -0
  113. package/dist/image-preview/style.css +96 -0
  114. package/dist/index.d.ts +46 -0
  115. package/dist/index.js +45 -0
  116. package/dist/list/index.d.ts +32 -0
  117. package/dist/list/index.js +42 -0
  118. package/dist/list/list-item.d.ts +27 -0
  119. package/dist/list/list-item.js +51 -0
  120. package/dist/list/style.css +20 -0
  121. package/dist/loading/index.d.ts +10 -0
  122. package/dist/loading/index.js +46 -0
  123. package/dist/loading/style.css +48 -0
  124. package/dist/menu/index.d.ts +38 -0
  125. package/dist/menu/index.js +62 -0
  126. package/dist/menu/leaf-item.d.ts +12 -0
  127. package/dist/menu/leaf-item.js +41 -0
  128. package/dist/menu/style.css +117 -0
  129. package/dist/menu/sub-menu.d.ts +21 -0
  130. package/dist/menu/sub-menu.js +85 -0
  131. package/dist/menu/types.d.ts +36 -0
  132. package/dist/menu/types.js +1 -0
  133. package/dist/menu/utils.d.ts +11 -0
  134. package/dist/menu/utils.js +24 -0
  135. package/dist/modal/index.d.ts +23 -0
  136. package/dist/modal/index.js +79 -0
  137. package/dist/modal/modal.d.ts +76 -0
  138. package/dist/modal/modal.js +188 -0
  139. package/dist/modal/style.css +90 -0
  140. package/dist/pagination/index.d.ts +31 -0
  141. package/dist/pagination/index.js +215 -0
  142. package/dist/pagination/style.css +50 -0
  143. package/dist/popconfirm/api.d.ts +43 -0
  144. package/dist/popconfirm/api.js +77 -0
  145. package/dist/popconfirm/component.d.ts +47 -0
  146. package/dist/popconfirm/component.js +48 -0
  147. package/dist/popconfirm/index.d.ts +3 -0
  148. package/dist/popconfirm/index.js +3 -0
  149. package/dist/popconfirm/style.css +22 -0
  150. package/dist/popover/api.d.ts +36 -0
  151. package/dist/popover/api.js +61 -0
  152. package/dist/popover/component.d.ts +38 -0
  153. package/dist/popover/component.js +51 -0
  154. package/dist/popover/index.d.ts +3 -0
  155. package/dist/popover/index.js +3 -0
  156. package/dist/popover/style.css +102 -0
  157. package/dist/progress/index.d.ts +34 -0
  158. package/dist/progress/index.js +70 -0
  159. package/dist/progress/style.css +37 -0
  160. package/dist/quick-input/index.d.ts +2 -0
  161. package/dist/quick-input/index.js +2 -0
  162. package/dist/quick-input/number.d.ts +35 -0
  163. package/dist/quick-input/number.js +68 -0
  164. package/dist/quick-input/text.d.ts +20 -0
  165. package/dist/quick-input/text.js +61 -0
  166. package/dist/result/index.d.ts +39 -0
  167. package/dist/result/index.js +71 -0
  168. package/dist/result/style.css +41 -0
  169. package/dist/search-box/index.d.ts +26 -0
  170. package/dist/search-box/index.js +60 -0
  171. package/dist/search-box/style.css +22 -0
  172. package/dist/segmented/index.d.ts +42 -0
  173. package/dist/segmented/index.js +61 -0
  174. package/dist/segmented/style.css +28 -0
  175. package/dist/skeleton/index.d.ts +22 -0
  176. package/dist/skeleton/index.js +68 -0
  177. package/dist/skeleton/style.css +31 -0
  178. package/dist/steps/index.d.ts +46 -0
  179. package/dist/steps/index.js +95 -0
  180. package/dist/steps/style.css +181 -0
  181. package/dist/switch/index.d.ts +32 -0
  182. package/dist/switch/index.js +74 -0
  183. package/dist/switch/style.css +52 -0
  184. package/dist/table/body.d.ts +21 -0
  185. package/dist/table/body.js +35 -0
  186. package/dist/table/column.d.ts +78 -0
  187. package/dist/table/column.js +113 -0
  188. package/dist/table/header.d.ts +13 -0
  189. package/dist/table/header.js +15 -0
  190. package/dist/table/index.d.ts +41 -0
  191. package/dist/table/index.js +84 -0
  192. package/dist/table/row.d.ts +25 -0
  193. package/dist/table/row.js +74 -0
  194. package/dist/table/style.css +98 -0
  195. package/dist/tabs/index.d.ts +49 -0
  196. package/dist/tabs/index.js +76 -0
  197. package/dist/tabs/style.css +41 -0
  198. package/dist/tag/index.d.ts +53 -0
  199. package/dist/tag/index.js +100 -0
  200. package/dist/tag/style.css +134 -0
  201. package/dist/text/index.d.ts +104 -0
  202. package/dist/text/index.js +143 -0
  203. package/dist/text/style.css +113 -0
  204. package/dist/theme/index.d.ts +14 -0
  205. package/dist/theme/index.js +94 -0
  206. package/dist/theme/themes.d.ts +3 -0
  207. package/dist/theme/themes.js +323 -0
  208. package/dist/theme/types.d.ts +58 -0
  209. package/dist/theme/types.js +1 -0
  210. package/dist/timeline/index.d.ts +28 -0
  211. package/dist/timeline/index.js +35 -0
  212. package/dist/timeline/style.css +53 -0
  213. package/dist/toast/index.d.ts +53 -0
  214. package/dist/toast/index.js +131 -0
  215. package/dist/toast/style.css +76 -0
  216. package/dist/tooltip/api.d.ts +44 -0
  217. package/dist/tooltip/api.js +103 -0
  218. package/dist/tooltip/component.d.ts +28 -0
  219. package/dist/tooltip/component.js +35 -0
  220. package/dist/tooltip/index.d.ts +3 -0
  221. package/dist/tooltip/index.js +3 -0
  222. package/dist/tooltip/style.css +46 -0
  223. package/dist/tree/dragging-img.d.ts +13 -0
  224. package/dist/tree/dragging-img.js +23 -0
  225. package/dist/tree/index.d.ts +180 -0
  226. package/dist/tree/index.js +385 -0
  227. package/dist/tree/node-info.d.ts +63 -0
  228. package/dist/tree/node-info.js +128 -0
  229. package/dist/tree/node.d.ts +132 -0
  230. package/dist/tree/node.js +264 -0
  231. package/dist/tree/style.css +99 -0
  232. package/dist/upload/index.d.ts +48 -0
  233. package/dist/upload/index.js +141 -0
  234. package/dist/upload/style.css +41 -0
  235. package/package.json +51 -0
@@ -0,0 +1,37 @@
1
+ import { DivModule, SubModulesOpt } from 'wok-ui';
2
+ import './style.less';
3
+ export interface DescriptionItem {
4
+ label: SubModulesOpt;
5
+ content: SubModulesOpt;
6
+ /**
7
+ * 条目独占一行.
8
+ */
9
+ exclusiveRow?: boolean;
10
+ }
11
+ /**
12
+ * 布局方式.
13
+ * vertical: 标题在内容上方;horizontal: 标题在内容左侧.
14
+ */
15
+ export type DescriptionListLayout = 'vertical' | 'horizontal';
16
+ export declare class DescriptionList extends DivModule {
17
+ constructor(opts: {
18
+ items: DescriptionItem[] | ((add: (...item: DescriptionItem[]) => void) => void);
19
+ cols?: number;
20
+ /**
21
+ * 间距(px),默认 24,bordered 模式下固定为 0
22
+ */
23
+ gap?: number;
24
+ /**
25
+ * 布局方式,默认 vertical
26
+ */
27
+ layout?: DescriptionListLayout;
28
+ /**
29
+ * 标题宽度(px),仅 layout 为 horizontal 时生效,默认 120
30
+ */
31
+ labelWidth?: number;
32
+ /**
33
+ * 是否带边框,默认 false
34
+ */
35
+ bordered?: boolean;
36
+ });
37
+ }
@@ -0,0 +1,145 @@
1
+ import { DivModule } from 'wok-ui';
2
+ import './style.css';
3
+ export class DescriptionList extends DivModule {
4
+ constructor(opts) {
5
+ // 外层容器,bordered 时负责圆角裁剪
6
+ super('wok-ui-ext-description-list');
7
+ const { items, cols = 3, gap = 24, layout = 'vertical', labelWidth, bordered = false } = opts;
8
+ this.el.style.setProperty('--dl-gap', `${gap}px`);
9
+ if (layout === 'horizontal') {
10
+ this.el.classList.add('layout-horizontal');
11
+ }
12
+ if (bordered) {
13
+ this.el.classList.add('bordered');
14
+ }
15
+ // 构建 items
16
+ const finalItems = [];
17
+ if (Array.isArray(items)) {
18
+ finalItems.push(...items);
19
+ }
20
+ else {
21
+ function add(...items) {
22
+ finalItems.push(...items);
23
+ }
24
+ items(add);
25
+ }
26
+ // table:colgroup 控制列宽(horizontal 每列拆为 label 列 + content 列),tbody 动态构建
27
+ this.addChild({
28
+ tag: 'table',
29
+ classNames: 'wok-ui-ext-description-table',
30
+ children: [
31
+ {
32
+ tag: 'colgroup',
33
+ children: Array.from({ length: layout === 'horizontal' ? cols * 2 : cols }, (_, i) => layout === 'horizontal' && i % 2 === 0
34
+ ? { tag: 'col', style: { width: `${labelWidth ?? 120}px` } }
35
+ : { tag: 'col' })
36
+ },
37
+ {
38
+ tag: 'tbody',
39
+ children: add => {
40
+ if (layout === 'horizontal') {
41
+ // 标题在左:label/content 为单元格,每行 cols 对
42
+ const perRow = cols * 2;
43
+ let rowCells = [];
44
+ const flushRow = () => {
45
+ if (rowCells.length > 0) {
46
+ if (rowCells.length < perRow) {
47
+ // 行尾条目占满剩余列:最后一个 content 合并剩余列
48
+ const last = rowCells[rowCells.length - 1];
49
+ last.attrs = { colspan: String(perRow - rowCells.length + 1) };
50
+ }
51
+ add({ tag: 'tr', children: rowCells });
52
+ rowCells = [];
53
+ }
54
+ };
55
+ for (const item of finalItems) {
56
+ if (item.exclusiveRow) {
57
+ flushRow();
58
+ add({
59
+ tag: 'tr',
60
+ children: [
61
+ { tag: 'td', classNames: 'wok-ui-ext-description-label', children: item.label },
62
+ {
63
+ tag: 'td',
64
+ classNames: 'wok-ui-ext-description-content',
65
+ attrs: { colspan: String(perRow - 1) },
66
+ children: item.content
67
+ }
68
+ ]
69
+ });
70
+ }
71
+ else {
72
+ rowCells.push({ tag: 'td', classNames: 'wok-ui-ext-description-label', children: item.label }, { tag: 'td', classNames: 'wok-ui-ext-description-content', children: item.content });
73
+ if (rowCells.length >= perRow) {
74
+ flushRow();
75
+ }
76
+ }
77
+ }
78
+ flushRow();
79
+ }
80
+ else {
81
+ // 标题在上:每组 cols 个条目,label 一行、content 一行
82
+ let group = [];
83
+ const flushGroup = () => {
84
+ if (group.length > 0) {
85
+ add({
86
+ tag: 'tr',
87
+ children: group.map(item => ({
88
+ tag: 'td',
89
+ classNames: 'wok-ui-ext-description-label',
90
+ children: item.label
91
+ }))
92
+ });
93
+ add({
94
+ tag: 'tr',
95
+ children: group.map(item => ({
96
+ tag: 'td',
97
+ classNames: 'wok-ui-ext-description-content',
98
+ children: item.content
99
+ }))
100
+ });
101
+ group = [];
102
+ }
103
+ };
104
+ for (const item of finalItems) {
105
+ if (item.exclusiveRow) {
106
+ // 独占一行:label 单独一行、content 单独一行,均占满整行
107
+ flushGroup();
108
+ add({
109
+ tag: 'tr',
110
+ children: [
111
+ {
112
+ tag: 'td',
113
+ classNames: 'wok-ui-ext-description-label',
114
+ attrs: { colspan: String(cols) },
115
+ children: item.label
116
+ }
117
+ ]
118
+ });
119
+ add({
120
+ tag: 'tr',
121
+ children: [
122
+ {
123
+ tag: 'td',
124
+ classNames: 'wok-ui-ext-description-content',
125
+ attrs: { colspan: String(cols) },
126
+ children: item.content
127
+ }
128
+ ]
129
+ });
130
+ }
131
+ else {
132
+ group.push(item);
133
+ if (group.length >= cols) {
134
+ flushGroup();
135
+ }
136
+ }
137
+ }
138
+ flushGroup();
139
+ }
140
+ }
141
+ }
142
+ ]
143
+ });
144
+ }
145
+ }
@@ -0,0 +1,63 @@
1
+ .wok-ui-ext-description-list {
2
+ width: 100%;
3
+ }
4
+ .wok-ui-ext-description-list.bordered {
5
+ border: 1px solid var(--border-light);
6
+ border-radius: var(--radius-md);
7
+ overflow: hidden;
8
+ }
9
+ .wok-ui-ext-description-list .wok-ui-ext-description-table {
10
+ width: 100%;
11
+ border-collapse: separate;
12
+ border-spacing: 0;
13
+ table-layout: fixed;
14
+ }
15
+ .wok-ui-ext-description-list .wok-ui-ext-description-table td {
16
+ vertical-align: top;
17
+ }
18
+ .wok-ui-ext-description-list .wok-ui-ext-description-label {
19
+ font-size: var(--font-size-xs);
20
+ font-weight: var(--font-weight-medium);
21
+ color: var(--text-tertiary);
22
+ white-space: nowrap;
23
+ }
24
+ .wok-ui-ext-description-list .wok-ui-ext-description-content {
25
+ font-size: var(--font-size-small);
26
+ color: var(--text-primary);
27
+ word-break: break-word;
28
+ line-height: 1.5;
29
+ }
30
+ .wok-ui-ext-description-list:not(.bordered).layout-horizontal td.wok-ui-ext-description-label,
31
+ .wok-ui-ext-description-list:not(.bordered).layout-horizontal td.wok-ui-ext-description-content {
32
+ padding: 6px 0;
33
+ }
34
+ .wok-ui-ext-description-list:not(.bordered).layout-horizontal td.wok-ui-ext-description-label {
35
+ padding-right: 8px;
36
+ overflow: hidden;
37
+ text-overflow: ellipsis;
38
+ }
39
+ .wok-ui-ext-description-list:not(.bordered).layout-horizontal td.wok-ui-ext-description-content {
40
+ padding-right: var(--dl-gap, 24px);
41
+ }
42
+ .wok-ui-ext-description-list:not(.bordered):not(.layout-horizontal) td.wok-ui-ext-description-label {
43
+ padding: 6px calc(var(--dl-gap, 24px) / 2) 0;
44
+ }
45
+ .wok-ui-ext-description-list:not(.bordered):not(.layout-horizontal) td.wok-ui-ext-description-content {
46
+ padding: 6px calc(var(--dl-gap, 24px) / 2) var(--dl-gap, 24px);
47
+ }
48
+ .wok-ui-ext-description-list.bordered td {
49
+ padding: 12px 16px;
50
+ border-right: 1px solid var(--border-light);
51
+ border-bottom: 1px solid var(--border-light);
52
+ }
53
+ .wok-ui-ext-description-list.bordered td:last-child {
54
+ border-right: none;
55
+ }
56
+ .wok-ui-ext-description-list.bordered tr:last-child td {
57
+ border-bottom: none;
58
+ }
59
+ .wok-ui-ext-description-list.bordered td.wok-ui-ext-description-label {
60
+ vertical-align: middle;
61
+ background: var(--bg-hover);
62
+ color: var(--text-secondary);
63
+ }
@@ -0,0 +1,29 @@
1
+ import { DivModule } from 'wok-ui';
2
+ import './style.less';
3
+ export interface DividerOpts {
4
+ /**
5
+ * 文字(水平模式时显示在中间)
6
+ */
7
+ text?: string;
8
+ /**
9
+ * 水平还是垂直,默认水平
10
+ */
11
+ direction?: 'horizontal' | 'vertical';
12
+ /**
13
+ * 虚线
14
+ */
15
+ dashed?: boolean;
16
+ /**
17
+ * 自定义文字颜色
18
+ */
19
+ color?: string;
20
+ }
21
+ /**
22
+ * 分割线
23
+ *
24
+ * 水平模式(默认):带文字或不带文字,用于区块分隔
25
+ * 垂直模式:用于行内元素之间的分隔
26
+ */
27
+ export declare class Divider extends DivModule {
28
+ constructor(opts?: DividerOpts);
29
+ }
@@ -0,0 +1,29 @@
1
+ import { DivModule } from 'wok-ui';
2
+ import './style.css';
3
+ /**
4
+ * 分割线
5
+ *
6
+ * 水平模式(默认):带文字或不带文字,用于区块分隔
7
+ * 垂直模式:用于行内元素之间的分隔
8
+ */
9
+ export class Divider extends DivModule {
10
+ constructor(opts = {}) {
11
+ const { direction = 'horizontal', dashed, color, text } = opts;
12
+ const classNames = `wok-ui-ext-divider wok-ui-ext-divider-${direction}`;
13
+ super(classNames);
14
+ if (dashed) {
15
+ this.el.classList.add('wok-ui-ext-divider-dashed');
16
+ }
17
+ if (text) {
18
+ this.el.classList.add('wok-ui-ext-divider-with-text');
19
+ this.addChild({
20
+ tag: 'span',
21
+ classNames: 'wok-ui-ext-divider-text',
22
+ innerText: text
23
+ });
24
+ }
25
+ if (color) {
26
+ this.el.style.setProperty('--divider-color', color);
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,50 @@
1
+ .wok-ui-ext-divider {
2
+ --divider-color: var(--border-light);
3
+ --divider-text-color: var(--text-tertiary);
4
+ --divider-text-bg: transparent;
5
+ --divider-text-padding: 16px;
6
+ border: 0;
7
+ display: flex;
8
+ align-items: center;
9
+ box-sizing: border-box;
10
+ }
11
+ .wok-ui-ext-divider-horizontal {
12
+ width: 100%;
13
+ border-top: 1px solid var(--divider-color);
14
+ }
15
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-with-text {
16
+ border-top: none;
17
+ }
18
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-with-text::before,
19
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-with-text::after {
20
+ content: '';
21
+ flex: 1;
22
+ border-top: 1px solid var(--divider-color);
23
+ }
24
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-dashed {
25
+ border-top-style: dashed;
26
+ }
27
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-dashed.wok-ui-ext-divider-with-text {
28
+ border-top: none;
29
+ }
30
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-dashed.wok-ui-ext-divider-with-text::before,
31
+ .wok-ui-ext-divider-horizontal.wok-ui-ext-divider-dashed.wok-ui-ext-divider-with-text::after {
32
+ border-top-style: dashed;
33
+ }
34
+ .wok-ui-ext-divider-horizontal .wok-ui-ext-divider-text {
35
+ padding: 0 var(--divider-text-padding);
36
+ font-size: var(--font-size-small);
37
+ color: var(--divider-text-color);
38
+ white-space: nowrap;
39
+ background: var(--divider-text-bg);
40
+ }
41
+ .wok-ui-ext-divider-vertical {
42
+ display: inline-flex;
43
+ height: 1em;
44
+ border-left: 1px solid var(--divider-color);
45
+ vertical-align: middle;
46
+ align-self: center;
47
+ }
48
+ .wok-ui-ext-divider-vertical.wok-ui-ext-divider-dashed {
49
+ border-left-style: dashed;
50
+ }
@@ -0,0 +1,51 @@
1
+ import { SubModulesOpt } from 'wok-ui';
2
+ import './style.less';
3
+ export interface DrawerOptions {
4
+ /**
5
+ * 从哪个方向滑出,默认 right
6
+ */
7
+ placement?: 'left' | 'right' | 'top' | 'bottom';
8
+ /**
9
+ * 标题
10
+ */
11
+ title?: string;
12
+ /**
13
+ * 宽度(仅 left/right 有效),默认 400px
14
+ */
15
+ width?: number;
16
+ /**
17
+ * 主体内容
18
+ */
19
+ body: SubModulesOpt;
20
+ /**
21
+ * 用 body 完全替换整个内容面板,
22
+ * 适用于完全自定义内容的场景。设为 true 时 title 不生效。
23
+ */
24
+ replaceByBody?: boolean;
25
+ /**
26
+ * 关闭回调
27
+ */
28
+ onClose?: () => void;
29
+ /**
30
+ * 入场动画完成后触发
31
+ */
32
+ onShown?: () => void;
33
+ }
34
+ export interface DrawerHandle {
35
+ close: () => void;
36
+ }
37
+ /**
38
+ * 打开抽屉
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const drawer = showDrawer({
43
+ * title: '详情',
44
+ * body: new MyForm()
45
+ * })
46
+ *
47
+ * // 手动关闭
48
+ * drawer.close()
49
+ * ```
50
+ */
51
+ export declare function showDrawer(opts: DrawerOptions): DrawerHandle;
@@ -0,0 +1,183 @@
1
+ import { DivModule } from 'wok-ui';
2
+ import { getWokUiExtI18n } from '../i18n';
3
+ import { IconTimes } from '../icons';
4
+ import './style.css';
5
+ // ─── 内容面板 ──────────────────────────────────────
6
+ class Content extends DivModule {
7
+ constructor(opts, onDestroy) {
8
+ const placement = opts.placement || 'right';
9
+ super('wok-ui-ext-drawer-content');
10
+ this.opts = opts;
11
+ this.onDestroy = onDestroy;
12
+ this.called = false;
13
+ this.animating = false;
14
+ this.el.classList.add(placement);
15
+ if (typeof opts.width === 'number' && (placement === 'left' || placement === 'right')) {
16
+ this.el.style.width = `${opts.width}px`;
17
+ }
18
+ const i18n = getWokUiExtI18n();
19
+ if (opts.replaceByBody) {
20
+ this.addChild(opts.body);
21
+ }
22
+ else {
23
+ // 头部
24
+ if (opts.title) {
25
+ this.addChild({
26
+ classNames: 'wok-ui-ext-drawer-header',
27
+ children: add => {
28
+ add({
29
+ tag: 'h3',
30
+ classNames: 'wok-ui-ext-drawer-title',
31
+ children: opts.title
32
+ });
33
+ add({
34
+ tag: 'button',
35
+ classNames: 'wok-ui-ext-drawer-close',
36
+ attrs: {
37
+ 'aria-label': i18n.buildMsg('modal-close')
38
+ },
39
+ children: new IconTimes(),
40
+ onClick: () => this.destroy()
41
+ });
42
+ }
43
+ });
44
+ }
45
+ // 主体
46
+ this.addChild({
47
+ classNames: 'wok-ui-ext-drawer-body',
48
+ children: opts.body
49
+ });
50
+ }
51
+ // 入口动画
52
+ this.animateIn(placement);
53
+ }
54
+ animateIn(placement) {
55
+ this.el.style.transition = 'transform 0.25s ease, opacity 0.25s ease';
56
+ // 从对应方向移入
57
+ const offsetMap = {
58
+ left: 'translateX(-100%)',
59
+ right: 'translateX(100%)',
60
+ top: 'translateY(-100%)',
61
+ bottom: 'translateY(100%)'
62
+ };
63
+ this.el.style.transform = offsetMap[placement] || offsetMap.right;
64
+ this.el.style.opacity = '0';
65
+ // 触发 reflow 后恢复原位
66
+ requestAnimationFrame(() => {
67
+ requestAnimationFrame(() => {
68
+ this.el.style.transform = 'translate(0, 0)';
69
+ this.el.style.opacity = '1';
70
+ setTimeout(() => this.opts.onShown?.(), 250);
71
+ });
72
+ });
73
+ }
74
+ animateOut() {
75
+ this.animating = true;
76
+ return new Promise(resolve => {
77
+ const placement = this.opts.placement || 'right';
78
+ const offsetMap = {
79
+ left: 'translateX(-100%)',
80
+ right: 'translateX(100%)',
81
+ top: 'translateY(-100%)',
82
+ bottom: 'translateY(100%)'
83
+ };
84
+ this.el.style.transform = offsetMap[placement] || offsetMap.right;
85
+ this.el.style.opacity = '0';
86
+ setTimeout(resolve, 250);
87
+ });
88
+ }
89
+ destroy() {
90
+ if (this.animating)
91
+ return;
92
+ if (this.called)
93
+ return;
94
+ this.called = true;
95
+ this.animating = true;
96
+ this.animateOut().then(() => {
97
+ super.destroy();
98
+ this.onDestroy();
99
+ this.opts.onClose?.();
100
+ });
101
+ }
102
+ }
103
+ // ─── 遮罩层 ──────────────────────────────────────────
104
+ class Backdrop extends DivModule {
105
+ constructor() {
106
+ super('wok-ui-ext-drawer-backdrop');
107
+ this.contents = [];
108
+ this.destroyed = false;
109
+ document.body.classList.add('wok-ui-ext-drawer-lock-scroll');
110
+ // 点击遮罩关闭最上层
111
+ this.el.addEventListener('click', () => {
112
+ if (this.contents.length === 0)
113
+ return;
114
+ this.contents[this.contents.length - 1].destroy();
115
+ });
116
+ // Escape 关闭
117
+ this.escHandler = (e) => {
118
+ if (e.key === 'Escape' && this.contents.length > 0) {
119
+ this.contents[this.contents.length - 1].destroy();
120
+ }
121
+ };
122
+ document.addEventListener('keydown', this.escHandler);
123
+ }
124
+ addContent(content) {
125
+ this.contents.push(content);
126
+ this.addChild(content);
127
+ }
128
+ removeContent(content) {
129
+ this.contents = this.contents.filter(c => c !== content);
130
+ if (this.contents.length === 0) {
131
+ this.destroy();
132
+ }
133
+ }
134
+ destroy() {
135
+ document.removeEventListener('keydown', this.escHandler);
136
+ // 清空所有 content
137
+ this.contents.forEach(c => {
138
+ try {
139
+ c.destroy();
140
+ }
141
+ catch {
142
+ // ignore
143
+ }
144
+ });
145
+ this.contents = [];
146
+ document.body.classList.remove('wok-ui-ext-drawer-lock-scroll');
147
+ this.destroyed = true;
148
+ super.destroy();
149
+ }
150
+ }
151
+ // ─── 全局 backdrop ──────────────────────────────────
152
+ let backdrop;
153
+ function getBackdrop() {
154
+ if (!backdrop || backdrop.destroyed) {
155
+ backdrop = new Backdrop();
156
+ backdrop.mount(document.body);
157
+ }
158
+ return backdrop;
159
+ }
160
+ /**
161
+ * 打开抽屉
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * const drawer = showDrawer({
166
+ * title: '详情',
167
+ * body: new MyForm()
168
+ * })
169
+ *
170
+ * // 手动关闭
171
+ * drawer.close()
172
+ * ```
173
+ */
174
+ export function showDrawer(opts) {
175
+ const bd = getBackdrop();
176
+ const content = new Content(opts, () => {
177
+ bd.removeContent(content);
178
+ });
179
+ bd.addContent(content);
180
+ return {
181
+ close: () => content.destroy()
182
+ };
183
+ }
@@ -0,0 +1,100 @@
1
+ .wok-ui-ext-drawer-backdrop {
2
+ position: fixed;
3
+ inset: 0;
4
+ z-index: 1050;
5
+ background: rgba(0, 0, 0, 0.45);
6
+ display: flex;
7
+ justify-content: flex-end;
8
+ animation: wok-ui-ext-drawer-fade-in 0.2s ease;
9
+ }
10
+ .wok-ui-ext-drawer-content {
11
+ display: flex;
12
+ flex-direction: column;
13
+ background: var(--bg-card);
14
+ box-shadow: -4px 0 24px rgba(0, 0, 0, 0.12);
15
+ position: absolute;
16
+ overflow: hidden;
17
+ }
18
+ .wok-ui-ext-drawer-content.right {
19
+ top: 0;
20
+ right: 0;
21
+ bottom: 0;
22
+ width: 400px;
23
+ max-width: 100vw;
24
+ border-radius: var(--radius-lg) 0 0 var(--radius-lg);
25
+ }
26
+ .wok-ui-ext-drawer-content.left {
27
+ top: 0;
28
+ left: 0;
29
+ bottom: 0;
30
+ width: 400px;
31
+ max-width: 100vw;
32
+ border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
33
+ box-shadow: 4px 0 24px rgba(0, 0, 0, 0.12);
34
+ }
35
+ .wok-ui-ext-drawer-content.top {
36
+ top: 0;
37
+ left: 0;
38
+ right: 0;
39
+ max-height: 90vh;
40
+ border-radius: 0 0 var(--radius-lg) var(--radius-lg);
41
+ }
42
+ .wok-ui-ext-drawer-content.bottom {
43
+ bottom: 0;
44
+ left: 0;
45
+ right: 0;
46
+ max-height: 90vh;
47
+ border-radius: var(--radius-lg) var(--radius-lg) 0 0;
48
+ }
49
+ .wok-ui-ext-drawer-header {
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: space-between;
53
+ padding: 20px 24px;
54
+ border-bottom: 1px solid var(--border-light);
55
+ flex-shrink: 0;
56
+ }
57
+ .wok-ui-ext-drawer-title {
58
+ font-size: var(--font-size-title);
59
+ font-weight: var(--font-weight-semibold);
60
+ color: var(--text-primary);
61
+ margin: 0;
62
+ }
63
+ .wok-ui-ext-drawer-close {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ width: 32px;
68
+ height: 32px;
69
+ border: none;
70
+ background: transparent;
71
+ border-radius: var(--radius-sm);
72
+ color: var(--text-tertiary);
73
+ cursor: pointer;
74
+ transition: background var(--transition-speed), color var(--transition-speed);
75
+ font-size: 18px;
76
+ }
77
+ .wok-ui-ext-drawer-close:hover {
78
+ background: var(--bg-hover);
79
+ color: var(--text-primary);
80
+ }
81
+ .wok-ui-ext-drawer-close svg {
82
+ width: 18px;
83
+ height: 18px;
84
+ }
85
+ .wok-ui-ext-drawer-body {
86
+ flex: 1;
87
+ overflow-y: auto;
88
+ padding: 24px;
89
+ }
90
+ body.wok-ui-ext-drawer-lock-scroll {
91
+ overflow: hidden;
92
+ }
93
+ @keyframes wok-ui-ext-drawer-fade-in {
94
+ from {
95
+ opacity: 0;
96
+ }
97
+ to {
98
+ opacity: 1;
99
+ }
100
+ }