artalk 2.0.4 → 2.1.1

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 (91) hide show
  1. package/README.md +7 -60
  2. package/dist/Artalk.css +1 -1
  3. package/dist/Artalk.es.js +5996 -1
  4. package/dist/Artalk.iife.js +266 -1
  5. package/dist/Artalk.js +266 -1
  6. package/package.json +3 -4
  7. package/src/api/index.ts +269 -0
  8. package/src/api/request.ts +125 -0
  9. package/src/artalk.ts +153 -0
  10. package/src/components/_component.ts.txt +10 -0
  11. package/src/components/action-btn.ts +169 -0
  12. package/src/components/admin/page-list.ts +194 -0
  13. package/src/components/admin/site-list-floater.ts +98 -0
  14. package/src/components/admin/site-list.ts +289 -0
  15. package/src/components/comment.ts +478 -0
  16. package/src/components/dialog.ts +63 -0
  17. package/src/components/editor-plugs/{_ExamplePlug.ts.txt → _example-plug.ts.txt} +0 -0
  18. package/src/components/editor-plugs/{EditorPlug.ts → editor-plug.ts} +3 -3
  19. package/src/components/editor-plugs/{EmoticonsPlug.less → emoticons-plug.less} +0 -0
  20. package/src/components/editor-plugs/{EmoticonsPlug.ts → emoticons-plug.ts} +9 -9
  21. package/src/components/editor-plugs/{PreviewPlug.less → preview-plug.less} +0 -0
  22. package/src/components/editor-plugs/{PreviewPlug.ts → preview-plug.ts} +10 -10
  23. package/src/components/{Editor.ts → editor.ts} +104 -102
  24. package/src/components/html/comment.html +2 -6
  25. package/src/components/html/list.html +0 -1
  26. package/src/components/html/sidebar.html +18 -4
  27. package/src/components/item-text-editor.ts +136 -0
  28. package/src/components/layer.ts +135 -0
  29. package/src/components/list-lite.ts +507 -0
  30. package/src/components/list.ts +172 -0
  31. package/src/components/pagination.ts +150 -0
  32. package/src/components/read-more-btn.ts +71 -0
  33. package/src/components/sidebar-view.ts +26 -0
  34. package/src/components/sidebar-views/comments-view.ts +66 -0
  35. package/src/components/sidebar-views/pages-view.ts +61 -0
  36. package/src/components/sidebar-views/setting-view.ts +21 -0
  37. package/src/components/sidebar-views/sites-view.ts +42 -0
  38. package/src/components/sidebar-views/transfer-view.ts +218 -0
  39. package/src/components/sidebar.ts +288 -0
  40. package/src/context.ts +42 -0
  41. package/src/default-conf.ts +42 -0
  42. package/src/lib/checker/admin-checker.ts +33 -0
  43. package/src/lib/checker/captcha-checker.ts +38 -0
  44. package/src/lib/checker/index.ts +134 -0
  45. package/src/lib/component.ts +3 -3
  46. package/src/lib/md5.js +6 -0
  47. package/src/lib/ui.ts +64 -74
  48. package/src/lib/user.ts +2 -8
  49. package/src/lib/utils.ts +30 -11
  50. package/src/main.ts +1 -1
  51. package/src/style/_color.less +8 -2
  52. package/src/style/_extend.less +81 -0
  53. package/src/style/_variables.less +3 -0
  54. package/src/style/comment.less +60 -24
  55. package/src/style/editor.less +3 -0
  56. package/src/style/item-text-editor.less +35 -0
  57. package/src/style/list.less +51 -32
  58. package/src/style/main.less +75 -1
  59. package/src/style/page-list.less +50 -0
  60. package/src/style/pagination.less +58 -0
  61. package/src/style/sidebar.less +274 -199
  62. package/src/style/site-list.less +208 -0
  63. package/tsconfig.json +27 -0
  64. package/types/artalk-config.d.ts +68 -51
  65. package/types/artalk-data.d.ts +38 -1
  66. package/types/event.d.ts +73 -0
  67. package/types/index.d.ts +1 -6
  68. package/.github/workflows/npm.yml +0 -31
  69. package/.github/workflows/pages.yml +0 -30
  70. package/dist/src/Event.d.ts +0 -59
  71. package/dist/types/artalk-config.d.ts +0 -79
  72. package/dist/types/artalk-data.d.ts +0 -153
  73. package/dist/types/global.d.ts +0 -1
  74. package/dist/types/index.d.ts +0 -8
  75. package/dist/types/vite-env.d.ts +0 -1
  76. package/example/pjax/res1.html +0 -41
  77. package/example/pjax/res2.html +0 -41
  78. package/src/Artalk.ts +0 -160
  79. package/src/Constant.ts +0 -6
  80. package/src/Context.ts +0 -34
  81. package/src/Event.d.ts +0 -59
  82. package/src/components/Comment.ts +0 -402
  83. package/src/components/Layer.ts +0 -138
  84. package/src/components/List.ts +0 -162
  85. package/src/components/ListLite.ts +0 -407
  86. package/src/components/Sidebar.ts +0 -141
  87. package/src/components/sidebar-views/AdminView.ts +0 -523
  88. package/src/components/sidebar-views/MessageView.ts +0 -48
  89. package/src/components/sidebar-views/SidebarView.ts +0 -24
  90. package/src/lib/api.ts +0 -380
  91. package/src/lib/checker.ts +0 -164
@@ -1,407 +0,0 @@
1
- import Context from '../Context'
2
- import Component from '../lib/component'
3
- import * as Utils from '../lib/utils'
4
- import * as Ui from '../lib/ui'
5
- import Api from '../lib/api'
6
- import Comment from './Comment'
7
- import { ListData, CommentData, NotifyData } from '~/types/artalk-data'
8
-
9
- export default class ListLite extends Component {
10
- public el: HTMLElement
11
- private commentsWrapEl: HTMLElement
12
- public comments: Comment[] = []
13
-
14
- public data?: ListData
15
- private pageSize: number = 15 // 每次请求获取量
16
- private offset: number = 0
17
- public type?: 'all'|'mentions'|'mine'|'pending'
18
-
19
- private readMoreEl: HTMLElement
20
- private readMoreLoadingEl: HTMLElement
21
- private readMoreTextEl: HTMLElement
22
-
23
- public noCommentText: string
24
- public renderComment?: (comment: Comment) => void
25
- public paramsEditor?: (params: any) => void
26
- public onAfterLoad?: (data: ListData) => void
27
-
28
- private isLoading: boolean = false
29
- public isFirstLoad = true
30
-
31
- public flatMode = false
32
-
33
- public unread: NotifyData[] = []
34
- public unreadHighlight = false
35
-
36
- constructor (ctx: Context) {
37
- super(ctx)
38
-
39
- this.el = Utils.createElement(`
40
- <div class="atk-list-lite">
41
- <div class="atk-list-comments-wrap"></div>
42
- <div class="atk-list-read-more" style="display: none;">
43
- <div class="atk-loading-icon" style="display: none;"></div>
44
- <span class="atk-text">查看更多</span>
45
- </div>
46
- </div>
47
- `)
48
- this.commentsWrapEl = this.el.querySelector('.atk-list-comments-wrap')!
49
-
50
- // 查看更多
51
- this.pageSize = this.conf.readMore ? (this.conf.readMore.pageSize || this.pageSize) : this.pageSize
52
- this.readMoreEl = this.el.querySelector('.atk-list-read-more')!
53
- this.readMoreLoadingEl = this.readMoreEl.querySelector('.atk-loading-icon')!
54
- this.readMoreTextEl = this.readMoreEl.querySelector('.atk-text')!
55
- this.readMoreEl.addEventListener('click', () => {
56
- this.readMore()
57
- })
58
-
59
- this.noCommentText = this.conf.noComment || '无评论'
60
-
61
- // 评论时间自动更新
62
- setInterval(() => {
63
- this.el.querySelectorAll<HTMLElement>('[data-atk-comment-date]').forEach(el => {
64
- const date = el.getAttribute('data-atk-comment-date')
65
- el.innerText = Utils.timeAgo(new Date(Number(date)))
66
- })
67
- }, 30 * 1000) // 30s 更新一次
68
-
69
- this.ctx.addEventListener('unread-update', (data) => (this.updateUnread(data.notifies)))
70
- }
71
-
72
- public async reqComments(offset: number = 0) {
73
- if (offset === 0) {
74
- this.clearComments()
75
- }
76
-
77
- // set loading
78
- this.isLoading = true
79
- if (offset === 0) Ui.showLoading(this.el)
80
- else this.readMoreBtnSetLoading(true)
81
-
82
- const hideLoading = () => {
83
- // hide loading
84
- this.isLoading = false
85
- if (offset === 0) Ui.hideLoading(this.el)
86
- else this.readMoreBtnSetLoading(false)
87
- }
88
-
89
- let listData: ListData
90
- try {
91
- listData = await new Api(this.ctx).get(offset, this.type, this.paramsEditor)
92
- } catch (e: any) {
93
- this.onError(e.msg || String(e))
94
- throw e
95
- } finally {
96
- hideLoading()
97
- }
98
-
99
- // load data
100
- this.offset = offset
101
-
102
- try {
103
- this.onLoad(listData)
104
-
105
- if (this.onAfterLoad) {
106
- this.onAfterLoad(listData)
107
- }
108
- } catch (e: any) {
109
- this.onError(String(e))
110
- throw e
111
- } finally {
112
- hideLoading()
113
- }
114
- }
115
-
116
- public onLoad (data: ListData) {
117
- this.data = data
118
- Ui.setError(this.el, null)
119
- this.importComments(data.comments)
120
-
121
- // 查看更多按钮
122
- if (this.hasMoreComments) {
123
- this.showReadMoreBtn()
124
- } else {
125
- this.hideReadMoreBtn()
126
- }
127
-
128
- // 滚动到底部自动加载
129
- if (this.isFirstLoad && this.hasMoreComments) {
130
- this.initScrollBottomAutoLoad()
131
- }
132
-
133
- this.ctx.dispatchEvent('unread-update', { notifies: data.unread || [] })
134
-
135
- this.isFirstLoad = false
136
- }
137
-
138
- public onError (msg: any) {
139
- msg = String(msg)
140
- console.error(msg)
141
- if (this.isFirstLoad) {
142
- const errEl = Utils.createElement(`<span>${msg},无法获取评论列表数据<br/></span>`)
143
- const retryBtn = Utils.createElement('<span style="cursor:pointer;">点击重新获取</span>')
144
- retryBtn.onclick = () => {
145
- this.reqComments(0)
146
- }
147
- errEl.appendChild(retryBtn)
148
- const adminBtn = Utils.createElement('<span atk-only-admin-show> | <span style="cursor:pointer;">打开控制台</span></span>')
149
- adminBtn.onclick = () => {
150
- this.ctx.dispatchEvent('sidebar-show', { viewName: 'admin' })
151
- }
152
- if (!this.ctx.user.data.isAdmin) {
153
- adminBtn.classList.add('atk-hide')
154
- }
155
- errEl.appendChild(adminBtn)
156
- Ui.setError(this.el, errEl)
157
- } else {
158
- this.readMoreBtnShowErr(`${msg} 获取失败`)
159
- }
160
- }
161
-
162
- public createComment(data: CommentData) {
163
- const comment = new Comment(this.ctx, data)
164
- comment.afterRender = () => {
165
- if (this.renderComment) this.renderComment(comment)
166
- }
167
- comment.onDelete = (c) => {
168
- this.deleteComment(c)
169
- this.refreshUI()
170
- }
171
-
172
- return comment
173
- }
174
-
175
- /** 导入评论 - 通过请求数据 */
176
- public importComments (rawData: CommentData[]) {
177
- // 查找并导入所有子评论
178
- const queryImportChildren = (parentC: Comment) => {
179
- const children = rawData.filter(o => o.rid === parentC.data.id)
180
- if (children.length === 0) return
181
-
182
- children.forEach((itemData: CommentData) => {
183
- itemData.is_allow_reply = parentC.data.is_allow_reply
184
- const childC = this.createComment(itemData)
185
- childC.renderElem()
186
- parentC.putChild(childC)
187
- queryImportChildren(childC) // 递归
188
- })
189
- }
190
-
191
- // 开始处理 rawData
192
- if (!this.flatMode) {
193
- rawData.filter((o) => o.rid === 0).forEach((rootCommentData: CommentData) => {
194
- if (rootCommentData.is_collapsed) rootCommentData.is_allow_reply = false
195
- const rootComment = this.createComment(rootCommentData)
196
- rootComment.renderElem()
197
- this.comments.push(rootComment) // 将评论导入 comments 总表中
198
-
199
- this.commentsWrapEl.appendChild(rootComment.getEl())
200
- rootComment.playFadeInAnim()
201
-
202
- queryImportChildren(rootComment)
203
- })
204
- } else {
205
- rawData.forEach((commentData: CommentData) => {
206
- if (commentData.is_collapsed) commentData.is_allow_reply = false
207
- const comment = this.createComment(commentData)
208
- if (commentData.rid !== 0) {
209
- const rComment = rawData.find(o => o.id === commentData.rid)
210
- if (rComment) comment.replyTo = rComment
211
- }
212
- comment.renderElem()
213
-
214
- this.comments.push(comment) // 将评论导入 comments 总表中
215
-
216
- if (commentData.visible) {
217
- this.commentsWrapEl.appendChild(comment.getEl())
218
- comment.playFadeInAnim()
219
- }
220
- })
221
- }
222
-
223
- this.refreshUI()
224
- }
225
-
226
- public insertComment (commentData: CommentData) {
227
- const comment = this.createComment(commentData)
228
- comment.renderElem()
229
-
230
- if (commentData.rid !== 0) {
231
- this.findComment(commentData.rid)?.putChild(comment)
232
- } else {
233
- this.commentsWrapEl.prepend(comment.getEl())
234
- this.comments.unshift(comment)
235
- }
236
-
237
- Ui.scrollIntoView(comment.getEl()) // 滚动到可以见
238
- comment.playFadeInAnim() // 播放评论渐出动画
239
- if (this.data) this.data.total += 1 // 评论数增加 1
240
- this.refreshUI() // 更新 list 界面
241
- }
242
-
243
- /** 刷新界面 */
244
- public refreshUI () {
245
- // 评论为空界面
246
- const noComment = this.comments.length <= 0
247
- let noCommentEl = this.commentsWrapEl.querySelector<HTMLElement>('.atk-list-no-comment')
248
-
249
- if (noComment) {
250
- if (!noCommentEl) {
251
- noCommentEl = Utils.createElement('<div class="atk-list-no-comment"></div>')
252
- this.commentsWrapEl.appendChild(noCommentEl)
253
- noCommentEl.innerHTML = this.noCommentText
254
- }
255
- }
256
-
257
- if (!noComment && noCommentEl)
258
- noCommentEl.remove()
259
-
260
- // 仅管理员显示控制
261
- this.ctx.dispatchEvent('check-admin-show-el')
262
- }
263
-
264
- /** 获取评论总数 (包括子评论) */
265
- public getListCommentCount (): number {
266
- if (!this.data || !this.data.total) return 0
267
- return Number(this.data.total || '0')
268
- }
269
-
270
- /** 是否还有更多的评论 */
271
- get hasMoreComments (): boolean {
272
- if (!this.data) return false
273
- return this.data.total_parents > (this.offset + this.pageSize)
274
- }
275
-
276
- /** 阅读更多操作 */
277
- async readMore () {
278
- const offset = this.offset + this.pageSize
279
- await this.reqComments(offset)
280
- }
281
-
282
- /** 阅读更多按钮 - 显示 */
283
- showReadMoreBtn () {
284
- this.readMoreEl.style.display = ''
285
- }
286
-
287
- /** 阅读更多按钮 - 隐藏 */
288
- hideReadMoreBtn () {
289
- this.readMoreEl.style.display = 'none'
290
- }
291
-
292
- /** 阅读更多按钮 - 显示加载 */
293
- readMoreBtnSetLoading (isLoading: boolean) {
294
- this.readMoreLoadingEl.style.display = isLoading ? '' : 'none'
295
- this.readMoreTextEl.style.display = isLoading ? 'none' : ''
296
- }
297
-
298
- /** 阅读更多按钮 - 显示错误 */
299
- readMoreBtnShowErr (errMsg: string) {
300
- this.readMoreBtnSetLoading(false)
301
-
302
- const readMoreTextOrg = this.readMoreTextEl.innerText
303
- this.readMoreTextEl.innerText = errMsg
304
- this.readMoreEl.classList.add('atk-err')
305
- setTimeout(() => {
306
- this.readMoreTextEl.innerText = readMoreTextOrg
307
- this.readMoreEl.classList.remove('atk-err')
308
- }, 2000) // 2s后错误提示复原
309
- }
310
-
311
- /** 初始化滚动到底部自动查看更多(若开启) */
312
- initScrollBottomAutoLoad () {
313
- if (!this.conf.readMore) return
314
- if (!this.conf.readMore.autoLoad) return
315
-
316
- document.addEventListener('scroll', () => {
317
- const targetEl = this.el.querySelector<HTMLElement>('.atk-list-comments-wrap > .atk-comment-wrap:nth-last-child(3)') // 获取倒数第3个评论元素
318
- if (!targetEl) return
319
- if (!this.hasMoreComments) return
320
- if (this.isLoading) return
321
- if (Ui.isVisible(targetEl)) {
322
- // 加载更多
323
- this.readMore()
324
- }
325
- })
326
- }
327
-
328
- /** 遍历操作 Comment (包括子评论) */
329
- public eachComment (commentList: Comment[], action: (comment: Comment, levelList: Comment[]) => boolean|void) {
330
- if (commentList.length === 0) return
331
- commentList.every((item) => {
332
- if (action(item, commentList) === false) return false
333
- this.eachComment(item.getChildren(), action)
334
- return true
335
- })
336
- }
337
-
338
- /** 查找评论项 */
339
- public findComment (id: number, src?: Comment[]): Comment|null {
340
- if (!src) src = this.comments
341
- let comment: Comment|null = null
342
- this.eachComment(src, (item) => {
343
- if (item.data.id === id) {
344
- comment = item
345
- return false
346
- }
347
- return true
348
- })
349
-
350
- return comment
351
- }
352
-
353
- /** 获取评论总数 */
354
- public getCommentCount (): number {
355
- let count = 0
356
- this.eachComment(this.comments, () => { count++ })
357
- return count
358
- }
359
-
360
- /** 删除评论 */
361
- public deleteComment (comment: number|Comment) {
362
- let findComment: Comment|null
363
- if (typeof comment === 'number') {
364
- findComment = this.findComment(comment)
365
- if (!findComment) throw Error(`未找到评论 ${comment}`)
366
- } else findComment = comment
367
-
368
- findComment.getEl().remove()
369
- this.eachComment(this.comments, (item, levelList) => {
370
- if (item === findComment) {
371
- levelList.splice(levelList.indexOf(item), 1)
372
- return false
373
- }
374
- return true
375
- })
376
- }
377
-
378
- /** 清空所有评论 */
379
- public clearComments () {
380
- this.commentsWrapEl.innerHTML = ''
381
- this.data = undefined
382
- this.comments = []
383
- }
384
-
385
- public updateUnread(notifies: NotifyData[]) {
386
- this.unread = notifies
387
-
388
- // 高亮评论
389
- if (this.unreadHighlight) {
390
- this.eachComment(this.comments, (comment) => {
391
- const notify = this.unread.find(o => o.comment_id === comment.data.id)
392
- if (notify) {
393
- comment.setUnread(true)
394
- comment.setOpenURL(notify.read_link)
395
- comment.openEvt = () => {
396
- this.unread = this.unread.filter(o => o.comment_id !== comment.data.id) // remove
397
- this.ctx.dispatchEvent('unread-update', {
398
- notifies: this.unread
399
- })
400
- }
401
- } else {
402
- comment.setUnread(false)
403
- }
404
- })
405
- }
406
- }
407
- }
@@ -1,141 +0,0 @@
1
- import '../style/sidebar.less'
2
-
3
- import Context from '../Context'
4
- import Component from '../lib/component'
5
- import * as Utils from '../lib/utils'
6
- import * as Ui from '../lib/ui'
7
- import Comment from './Comment'
8
- import SidebarHTML from './html/sidebar.html?raw'
9
- import BuildLayer, { Layer } from './Layer'
10
-
11
- import SidebarView from './sidebar-views/SidebarView'
12
- import MessageView from './sidebar-views/MessageView'
13
- import AdminView from './sidebar-views/AdminView'
14
-
15
- export default class Sidebar extends Component {
16
- public el: HTMLElement
17
- public layer?: Layer
18
- public actionsEl: HTMLElement
19
- public contentEl: HTMLElement
20
- public titleWrapEl: HTMLElement
21
-
22
- public view?: SidebarView
23
- public action?: string
24
- private isFirstShow = true
25
-
26
- public viewInstances: {[name: string]: SidebarView} = {}
27
- public registerViews: (typeof SidebarView)[] = [
28
- MessageView, AdminView,
29
- ]
30
-
31
- constructor (ctx: Context) {
32
- super(ctx)
33
-
34
- // initial elements
35
- this.el = Utils.createElement(SidebarHTML)
36
- this.contentEl = this.el.querySelector('.atk-sidebar-content')!
37
- this.titleWrapEl = this.el.querySelector('.atk-sidebar-title-wrap')!
38
- this.actionsEl = this.el.querySelector('.atk-sidebar-actions')!
39
-
40
- this.el.querySelector('.atk-sidebar-close')!.addEventListener('click', () => {
41
- this.hide()
42
- })
43
-
44
- // event
45
- this.ctx.addEventListener('sidebar-show', (payload) => (this.show(payload?.viewName)))
46
- this.ctx.addEventListener('sidebar-hide', () => (this.hide()))
47
-
48
- // titles
49
- this.registerViews.forEach(View => {
50
- const viewInstance = new View(this.ctx)
51
- this.viewInstances[viewInstance.name] = viewInstance
52
- viewInstance.el.classList.add(`atk-sidebar-view-${viewInstance.name}`)
53
-
54
- const titleEl = Utils.createElement(`
55
- <span class="atk-title-item" data-name="${viewInstance.name}">${viewInstance.title}</span>
56
- `)
57
- if (viewInstance.adminOnly) {
58
- titleEl.setAttribute('atk-only-admin-show', '')
59
- if (!this.ctx.user.data.isAdmin)
60
- titleEl.classList.add('atk-hide')
61
- }
62
- this.titleWrapEl.append(titleEl)
63
-
64
- // title click
65
- titleEl.addEventListener('click', () => { this.switchView(viewInstance) })
66
- })
67
- }
68
-
69
- show (viewName?: string) {
70
- this.el.style.transform = '' // 动画清除,防止二次打开失效
71
-
72
- this.layer = BuildLayer(this.ctx, 'sidebar', this.el)
73
- this.layer.show()
74
- this.contentEl.scrollTo(0, 0)
75
-
76
- setTimeout(() => {
77
- this.el.style.transform = 'translate(0, 0)' // 执行动画
78
- }, 20)
79
-
80
- if (viewName) {
81
- this.switchViewByName(viewName) // 打开指定 view
82
- }
83
-
84
- if (this.isFirstShow) {
85
- if (!viewName) this.switchViewByName('message') // 打开默认 view
86
- this.isFirstShow = false
87
- }
88
- }
89
-
90
- hide () {
91
- this.el.style.transform = ''
92
- this.layer?.dispose() // 用完即销毁
93
- }
94
-
95
- switchViewByName (viewName: string) {
96
- if (!this.viewInstances[viewName]) {
97
- console.error(`未找到 view: ${viewName}`)
98
- return
99
- }
100
-
101
- this.switchView(this.viewInstances[viewName])
102
- }
103
-
104
- switchView (view: SidebarView) {
105
- this.view = view
106
-
107
- // focus title
108
- const titleEl = this.titleWrapEl.querySelector<HTMLElement>(`[data-name=${view.name}]`)!
109
- this.titleWrapEl.querySelector<HTMLElement>('.atk-active')!.innerText = view.title
110
- this.titleWrapEl.querySelectorAll<HTMLElement>('.atk-title-item').forEach((item) => {
111
- if (!item.classList.contains('atk-active'))
112
- item.style.display = ''
113
- })
114
- titleEl.style.display = 'none'
115
-
116
- // init view ui
117
- view.init()
118
- this.contentEl.innerHTML = ''
119
- this.contentEl.append(view.el)
120
-
121
- // actions
122
- this.actionsEl.innerHTML = ''
123
- Object.entries(view.actions).forEach(([name, label]) => {
124
- const actionItemEl = Utils.createElement(`<span class="atk-action-item">${label}</span>`)
125
- this.actionsEl.append(actionItemEl)
126
-
127
- if (view.activeAction === name) actionItemEl.classList.add('atk-active')
128
-
129
- // action click
130
- actionItemEl.addEventListener('click', () => {
131
- view.switch(name)
132
- view.activeAction = name
133
-
134
- this.actionsEl.querySelectorAll('.atk-active').forEach((item) => {
135
- item.classList.remove('atk-active')
136
- })
137
- actionItemEl.classList.add('atk-active')
138
- })
139
- })
140
- }
141
- }