@acorex/components 22.4.14 → 22.4.16
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.
- package/comment/README.md +467 -2
- package/fesm2022/acorex-components-calendar.mjs +2 -2
- package/fesm2022/acorex-components-calendar.mjs.map +1 -1
- package/fesm2022/acorex-components-comment.mjs +36 -6
- package/fesm2022/acorex-components-comment.mjs.map +1 -1
- package/fesm2022/acorex-components-scheduler.mjs +2 -2
- package/fesm2022/acorex-components-scheduler.mjs.map +1 -1
- package/fesm2022/acorex-components-text-editor.mjs +34 -7
- package/fesm2022/acorex-components-text-editor.mjs.map +1 -1
- package/package.json +3 -3
- package/types/acorex-components-comment.d.ts +20 -3
- package/types/acorex-components-text-editor.d.ts +15 -2
package/comment/README.md
CHANGED
|
@@ -1,3 +1,468 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Comment (`@acorex/components/comment`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
کامپوننت ترد کامنت برای Angular. داده را بهصورت درخت (`AXCommentItem`) میگیرد، لایک/ریپلای/اکشن را مدیریت میکند، و ادیتور را در فوتر نگه میدارد.
|
|
4
|
+
|
|
5
|
+
## نصب و import
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
AXCommentModule,
|
|
10
|
+
AXCommentViewComponent,
|
|
11
|
+
AXCommentReplyComponent,
|
|
12
|
+
AXCommentItemTemplateDirective,
|
|
13
|
+
type AXCommentItem,
|
|
14
|
+
type AXCommentCallback,
|
|
15
|
+
type AXCommentActionEvent,
|
|
16
|
+
type AXCommentReplyEvent,
|
|
17
|
+
} from '@acorex/components/comment';
|
|
18
|
+
import { AXTextEditorModule } from '@acorex/components/text-editor';
|
|
19
|
+
import { AXDialogService } from '@acorex/components/dialog';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Standalone:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
imports: [AXCommentModule, AXTextEditorModule, FormsModule]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## معماری
|
|
31
|
+
|
|
32
|
+
| قطعه | سلکتور | نقش |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `AXCommentContainerComponent` | `ax-comment-container` | شِل با اسلات `ax-header` / `ax-footer` |
|
|
35
|
+
| `AXCommentViewComponent` | `ax-comment-view` | درخت داده، lazy load، متدهای mutate |
|
|
36
|
+
| `AXCommentItemComponent` | `ax-comment-item` | یک کامنت (لیآوت پیشفرض یا تمپلیت) |
|
|
37
|
+
| `AXCommentReplyComponent` | `ax-comment-reply` | نوار «در حال پاسخ به» بالای ادیتور |
|
|
38
|
+
| `AXCommentItemTemplateDirective` | `ng-template[axCommentItem]` | سفارشیسازی بدنه آیتم |
|
|
39
|
+
|
|
40
|
+
بدون `datasource` میتوان آیتمها را بهصورت declarative داخل `ax-comment-view` پروجکت کرد.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## مدل داده `AXCommentItem`
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
interface AXCommentItem {
|
|
48
|
+
id: string | number;
|
|
49
|
+
author: string;
|
|
50
|
+
avatar?: string;
|
|
51
|
+
initials?: string;
|
|
52
|
+
color?: AXStyleColorType;
|
|
53
|
+
date?: string;
|
|
54
|
+
edited?: boolean; // برچسب «ویرایششده» قبل از زمان
|
|
55
|
+
editedAt?: string; // tooltip روی برچسب (اختیاری)
|
|
56
|
+
content?: string; // HTML مجاز است؛ در UI پیشفرض با innerHTML رندر میشود
|
|
57
|
+
likes?: number;
|
|
58
|
+
liked?: boolean;
|
|
59
|
+
isYou?: boolean; // کنار نام، badge «You»
|
|
60
|
+
repliesExpanded?: boolean;
|
|
61
|
+
replies?: AXCommentItem[]; // eager
|
|
62
|
+
replyCount?: number; // برای lazy؛ اگر replies خالی باشد از این استفاده میشود
|
|
63
|
+
actions?: AXMenuItem[]; // منوی ... فقط در UI پیشفرض
|
|
64
|
+
data?: unknown;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`actions` همان `AXMenuItem` است:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const actions: AXMenuItem[] = [
|
|
72
|
+
{ name: 'edit', text: 'Edit', icon: 'ax-icon ax-icon-pen', break: true },
|
|
73
|
+
{ name: 'delete', text: 'Delete', icon: 'ax-icon ax-icon-trash', color: 'danger' },
|
|
74
|
+
];
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## ۱) استفاده پیشفرض (بدون تمپلیت)
|
|
80
|
+
|
|
81
|
+
Like و Reply داخل خود آیتم کار میکنند. رویدادها اختیاریاند.
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<ax-comment-container>
|
|
85
|
+
<ax-comment-view
|
|
86
|
+
#commentsView
|
|
87
|
+
[datasource]="comments"
|
|
88
|
+
(onReply)="onReply($event)"
|
|
89
|
+
(onLikeChange)="onLikeChange($event)"
|
|
90
|
+
(onRepliesToggle)="onRepliesToggle($event)"
|
|
91
|
+
(onAction)="onAction($event)"
|
|
92
|
+
/>
|
|
93
|
+
|
|
94
|
+
<ax-footer>
|
|
95
|
+
<ax-comment-reply [item]="replyingTo()" (onClose)="cancelReply()">
|
|
96
|
+
<ax-text-editor
|
|
97
|
+
#commentEditor
|
|
98
|
+
look="solid"
|
|
99
|
+
outputFormat="html"
|
|
100
|
+
[initialLine]="3"
|
|
101
|
+
[ngModel]="draft()"
|
|
102
|
+
(ngModelChange)="draft.set($event)"
|
|
103
|
+
[placeHolder]="replyingTo() ? 'Write your content...' : 'Write a comment...'"
|
|
104
|
+
>
|
|
105
|
+
<ax-footer>
|
|
106
|
+
<ax-button class="ax-sm" look="solid" color="primary" text="Send" (onClick)="send()" />
|
|
107
|
+
</ax-footer>
|
|
108
|
+
<ax-text-editor-toolbar>
|
|
109
|
+
<ax-text-editor-history />
|
|
110
|
+
<ax-text-editor-font-style />
|
|
111
|
+
<ax-text-editor-colors />
|
|
112
|
+
<ax-text-editor-list />
|
|
113
|
+
<ax-text-editor-alignment />
|
|
114
|
+
<ax-text-editor-media />
|
|
115
|
+
</ax-text-editor-toolbar>
|
|
116
|
+
</ax-text-editor>
|
|
117
|
+
</ax-comment-reply>
|
|
118
|
+
</ax-footer>
|
|
119
|
+
</ax-comment-container>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
comments = signal<AXCommentItem[]>([
|
|
124
|
+
{
|
|
125
|
+
id: 1,
|
|
126
|
+
author: 'Heidi Thonig',
|
|
127
|
+
initials: 'H',
|
|
128
|
+
color: 'success',
|
|
129
|
+
date: '18 hours ago',
|
|
130
|
+
content: 'The new layout looks great!',
|
|
131
|
+
likes: 1,
|
|
132
|
+
liked: true,
|
|
133
|
+
repliesExpanded: true,
|
|
134
|
+
actions,
|
|
135
|
+
replies: [
|
|
136
|
+
{
|
|
137
|
+
id: 2,
|
|
138
|
+
author: 'You',
|
|
139
|
+
initials: 'Y',
|
|
140
|
+
isYou: true,
|
|
141
|
+
date: 'Just now',
|
|
142
|
+
content: 'Agreed.',
|
|
143
|
+
likes: 0,
|
|
144
|
+
actions,
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
]);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
سه نقطه (`...`) فقط در لیآوت پیشفرض است، روی هاور همان کامنت ظاهر میشود، و از `item.actions` میآید.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## ۲) Lazy loading
|
|
156
|
+
|
|
157
|
+
`datasource` میتواند تابع باشد:
|
|
158
|
+
|
|
159
|
+
- بدون `id` → ریشهها
|
|
160
|
+
- با `id` → پاسخهای همان کامنت
|
|
161
|
+
|
|
162
|
+
برای ریشه، `replies` را نفرستید و `replyCount` بگذارید. وقتی کاربر ترد را باز کند، view دوباره callback را با id والد صدا میزند.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
readonly loadComments: AXCommentCallback = (id) => {
|
|
166
|
+
if (!id) {
|
|
167
|
+
return this.api.listRoots().then((rows) =>
|
|
168
|
+
rows.map((row) => ({
|
|
169
|
+
...row,
|
|
170
|
+
replyCount: row.replyCount ?? 0,
|
|
171
|
+
// replies را حذف کنید تا lazy بماند
|
|
172
|
+
})),
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
return this.api.listReplies(id);
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<ax-comment-view [datasource]="loadComments" (onReply)="onReply($event)" />
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
اسکلتون تا لود ریشه نشان داده میشود. باز/بسته کردن پاسخها `(onRepliesToggle)` میدهد.
|
|
184
|
+
|
|
185
|
+
برنامه میتواند از بیرون هم باز کند:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
this.commentsView()?.setExpanded('1', true);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## ۳) تمپلیت سفارشی
|
|
194
|
+
|
|
195
|
+
بدنه آیتم عوض میشود؛ ردیف Like / Reply / تعداد پاسخها همان chrome پیشفرض میماند. منوی `...` در تمپلیت سفارشی نشان داده نمیشود.
|
|
196
|
+
|
|
197
|
+
```html
|
|
198
|
+
<ax-comment-view [datasource]="comments()" (onReply)="onReply($event)" (onLikeChange)="onLike($event)">
|
|
199
|
+
<ng-template axCommentItem let-item let-level="level" let-reply="reply">
|
|
200
|
+
<div class="my-card" [class.is-reply]="level > 0">
|
|
201
|
+
<ax-avatar [color]="item.color" [size]="48" look="solid" shape="soft">
|
|
202
|
+
<ax-text>{{ item.initials }}</ax-text>
|
|
203
|
+
</ax-avatar>
|
|
204
|
+
<ax-title>{{ item.author }}</ax-title>
|
|
205
|
+
<ax-content>
|
|
206
|
+
<div [innerHTML]="item.content"></div>
|
|
207
|
+
</ax-content>
|
|
208
|
+
</div>
|
|
209
|
+
</ng-template>
|
|
210
|
+
</ax-comment-view>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
کانتکست تمپلیت (`AXCommentItemTemplateContext`):
|
|
214
|
+
|
|
215
|
+
| فیلد | معنی |
|
|
216
|
+
| --- | --- |
|
|
217
|
+
| `$implicit` / `item` | خود `AXCommentItem` |
|
|
218
|
+
| `level` | عمق (۰ = ریشه) |
|
|
219
|
+
| `repliesExpanded` | باز بودن پاسخها |
|
|
220
|
+
| `replyCount` | تعداد پاسخ |
|
|
221
|
+
| `loading` | در حال لود lazy |
|
|
222
|
+
| `liked` / `likes` | وضعیت لایک |
|
|
223
|
+
| `toggleReplies()` | باز/بسته کردن |
|
|
224
|
+
| `toggleLike()` | لایک |
|
|
225
|
+
| `reply(event?)` | شروع ریپلای |
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## ۴) Composer: ارسال، ریپلای، ویرایش
|
|
230
|
+
|
|
231
|
+
`ax-comment-reply` ادیتور را پروجکت میکند. اگر `item` ست باشد نوار «Replying to [نام]» با excerpt متنساده بالای ادیتور میآید. کلیک روی نوار به همان کامنت اسکرول و highlight میکند. X فقط target را میبندد؛ پیشنویس پاک نمیشود.
|
|
232
|
+
|
|
233
|
+
### Reply
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
replyingTo = signal<AXCommentItem | null>(null);
|
|
237
|
+
|
|
238
|
+
onReply(event: AXCommentReplyEvent) {
|
|
239
|
+
this.replyingTo.set(event.item);
|
|
240
|
+
setTimeout(() => this.editor()?.focus());
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
cancelReply() {
|
|
244
|
+
this.replyingTo.set(null); // draft باقی میماند
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
عوض کردن هدف ریپلای draft را نگه میدارد.
|
|
249
|
+
|
|
250
|
+
### Send
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
send() {
|
|
254
|
+
const html = this.draft();
|
|
255
|
+
if (this.isEmpty(html)) return; // fail: draft و target میمانند
|
|
256
|
+
|
|
257
|
+
const item: AXCommentItem = {
|
|
258
|
+
id: crypto.randomUUID(),
|
|
259
|
+
author: 'You',
|
|
260
|
+
initials: 'Y',
|
|
261
|
+
isYou: true,
|
|
262
|
+
date: 'Just now',
|
|
263
|
+
content: html,
|
|
264
|
+
likes: 0,
|
|
265
|
+
actions,
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const parent = this.replyingTo();
|
|
269
|
+
const view = this.commentsView();
|
|
270
|
+
|
|
271
|
+
if (parent) {
|
|
272
|
+
const parentId = String(parent.id);
|
|
273
|
+
if (view && !view.findItem(parentId)) return;
|
|
274
|
+
void view?.appendReply(parentId, item);
|
|
275
|
+
this.replyingTo.set(null);
|
|
276
|
+
} else {
|
|
277
|
+
view?.appendItem(item);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
this.draft.set('');
|
|
281
|
+
this.editor()?.setContent('', false);
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`ax-text-editor` برای ارتفاع از `[initialLine]="3"` استفاده میکند. برای ست کردن محتوا و فوکوس:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
this.editor()?.setContent(html, true);
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Edit / Delete (از منوی ...)
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
onAction(event: AXCommentActionEvent) {
|
|
295
|
+
if (event.action.name === 'edit') this.edit(event.item);
|
|
296
|
+
if (event.action.name === 'delete') void this.remove(event.item);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
edit(item: AXCommentItem) {
|
|
300
|
+
this.replyingTo.set(null);
|
|
301
|
+
this.editing.set(item);
|
|
302
|
+
this.editor()?.setContent(item.content ?? '', true);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
saveEdit() {
|
|
306
|
+
const html = this.draft();
|
|
307
|
+
const current = this.editing();
|
|
308
|
+
if (!current || this.isEmpty(html)) return;
|
|
309
|
+
const updated = this.commentsView()?.updateItem(String(current.id), { content: html, edited: true });
|
|
310
|
+
if (!updated) return;
|
|
311
|
+
this.editing.set(null);
|
|
312
|
+
this.draft.set('');
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async remove(item: AXCommentItem) {
|
|
316
|
+
const { result } = await this.dialog.confirm(
|
|
317
|
+
'Delete comment',
|
|
318
|
+
'This comment will be permanently removed.',
|
|
319
|
+
'danger',
|
|
320
|
+
);
|
|
321
|
+
if (!result) return;
|
|
322
|
+
this.commentsView()?.removeItem(String(item.id));
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
اگر datasource تابع lazy است، بعد از `appendItem` / `removeItem` / `updateItem` منبع خودتان (mock API / سیگنال) را هم همگام کنید تا reload بعدی درست باشد.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## ۵) APIی `ax-comment-view`
|
|
331
|
+
|
|
332
|
+
### Inputs / model
|
|
333
|
+
|
|
334
|
+
| نام | نوع | توضیح |
|
|
335
|
+
| --- | --- | --- |
|
|
336
|
+
| `datasource` | `AXCommentItem[] \| AXCommentCallback \| null` | آرایه یا callback تنبل |
|
|
337
|
+
| `itemTemplate` | `TemplateRef<AXCommentItemTemplateContext>` | جایگزین `ng-template axCommentItem` |
|
|
338
|
+
|
|
339
|
+
### Events
|
|
340
|
+
|
|
341
|
+
| نام | payload | کی |
|
|
342
|
+
| --- | --- | --- |
|
|
343
|
+
| `onReply` | `AXCommentReplyEvent` | کلیک Reply |
|
|
344
|
+
| `onLikeChange` | `AXCommentLikeChangeEvent` | تغییر لایک (view خودش liked/likes را آپدیت میکند) |
|
|
345
|
+
| `onRepliesToggle` | `AXCommentRepliesToggleEvent` | باز/بسته شدن پاسخها |
|
|
346
|
+
| `onAction` | `AXCommentActionEvent` | انتخاب آیتم منوی `...` — `event.action` از نوع `AXMenuItem` |
|
|
347
|
+
|
|
348
|
+
### Methods
|
|
349
|
+
|
|
350
|
+
| متد | کار |
|
|
351
|
+
| --- | --- |
|
|
352
|
+
| `reloadData()` | ریشهها را دوباره از datasource میگیرد |
|
|
353
|
+
| `appendItem(item)` | کامنت ریشه اضافه میکند |
|
|
354
|
+
| `appendReply(parentId, item)` | پاسخ میگذارد؛ اگر لازم باشد اول lazy load میکند و والد را باز میکند |
|
|
355
|
+
| `findItem(id)` | جستجو در درخت لودشده |
|
|
356
|
+
| `updateItem(id, patch)` | پچ آیتم؛ `id` اصلی حفظ میشود |
|
|
357
|
+
| `removeItem(id)` | حذف آیتم و پاسخهای تو در تو |
|
|
358
|
+
| `setExpanded(id, expanded)` | باز/بسته + lazy load |
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
const view = viewChild('commentsView', { read: AXCommentViewComponent });
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## ۶) `ax-comment-reply`
|
|
367
|
+
|
|
368
|
+
| | |
|
|
369
|
+
| --- | --- |
|
|
370
|
+
| `[item]` | `AXCommentItem \| null` — نوار فقط وقتی مقدار دارد دیده میشود |
|
|
371
|
+
| `(onClose)` | کلیک X |
|
|
372
|
+
| `(onTargetClick)` | کلیک روی نوار؛ خود کامپوننت هم اسکرول/highlight میکند |
|
|
373
|
+
|
|
374
|
+
Excerpt HTML را strip میکند و متن ساده نشان میدهد.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## ۷) `ax-comment-container`
|
|
379
|
+
|
|
380
|
+
اسلاتها: `ax-header`، محتوا، `ax-footer`.
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
scrollToReply(id: string): void
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
هر دو سلکتور را امتحان میکند: `ax-comment-item[id="…"]` و `comment-${id}`. view برای آیتمها `id="comment-${id}"` میگذارد.
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## ۸) حالت declarative (بدون datasource)
|
|
391
|
+
|
|
392
|
+
```html
|
|
393
|
+
<ax-comment-view>
|
|
394
|
+
<ax-comment-item [replyCount]="1" [(repliesExpanded)]="open">
|
|
395
|
+
<ax-avatar color="success" look="twotone" shape="rounded">
|
|
396
|
+
<ax-text>H</ax-text>
|
|
397
|
+
</ax-avatar>
|
|
398
|
+
<ax-title>Heidi Thonig</ax-title>
|
|
399
|
+
<ax-comment-date>18 hours ago</ax-comment-date>
|
|
400
|
+
<ax-content>Hello</ax-content>
|
|
401
|
+
<ax-comment-like [like]="true">1</ax-comment-like>
|
|
402
|
+
<ax-comment-reply-text (click)="onReply($event)" />
|
|
403
|
+
|
|
404
|
+
<ax-comment-item>
|
|
405
|
+
<ax-avatar color="primary" look="twotone" shape="rounded">
|
|
406
|
+
<ax-text>A</ax-text>
|
|
407
|
+
</ax-avatar>
|
|
408
|
+
<ax-title>Alex</ax-title>
|
|
409
|
+
<ax-content>Hi</ax-content>
|
|
410
|
+
<ax-comment-like [like]="false">0</ax-comment-like>
|
|
411
|
+
<ax-comment-reply-text />
|
|
412
|
+
</ax-comment-item>
|
|
413
|
+
</ax-comment-item>
|
|
414
|
+
</ax-comment-view>
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## ۹) i18n
|
|
420
|
+
|
|
421
|
+
کلیدها در `@acorex/core` (`comment.*`):
|
|
422
|
+
|
|
423
|
+
| کلید | en-US |
|
|
424
|
+
| --- | --- |
|
|
425
|
+
| `comment.reply` | Reply |
|
|
426
|
+
| `comment.replies` | Replies |
|
|
427
|
+
| `comment.replying-to` | Replying to |
|
|
428
|
+
| `comment.you` | You |
|
|
429
|
+
| `comment.edited` | Edited |
|
|
430
|
+
| `comment.view` | View |
|
|
431
|
+
| `comment.hide` | Hide |
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## ۱۰) توکنهای CSS
|
|
436
|
+
|
|
437
|
+
روی `ax-comment-container`:
|
|
438
|
+
|
|
439
|
+
| توکن | پیشفرض |
|
|
440
|
+
| --- | --- |
|
|
441
|
+
| `--ax-comp-comment-padding-y` | `8px` |
|
|
442
|
+
| `--ax-comp-comment-gap` | `8px` |
|
|
443
|
+
| `--ax-comp-comment-avatar-size` | `32px` |
|
|
444
|
+
| `--ax-comp-comment-reply-avatar-size` | `28px` |
|
|
445
|
+
|
|
446
|
+
لیآوت پیشفرض آیتم avatar را `48px` میگذارد. فاصله داخلی آیتم از `--ax-comp-comment-gap` (پیشفرض `0.5rem` روی خود آیتم) است.
|
|
447
|
+
|
|
448
|
+
نوار ریپلای:
|
|
449
|
+
|
|
450
|
+
| توکن | نقش |
|
|
451
|
+
| --- | --- |
|
|
452
|
+
| `--ax-comp-comment-reply-bar-bg-color` | پسزمینه |
|
|
453
|
+
| `--ax-comp-comment-reply-bar-border-color` | حاشیه |
|
|
454
|
+
| `--ax-comp-comment-reply-bar-accent-color` | نوار تأکیدی اینلایناستارت |
|
|
455
|
+
| `--ax-comp-comment-reply-bar-radius` | `6px` |
|
|
456
|
+
| `--ax-comp-comment-reply-bar-gap` | فاصله تا ادیتور (`8px`) |
|
|
457
|
+
|
|
458
|
+
Highlight اسکرول: کلاس `ax-state-highlight` روی `ax-comment-item`.
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## نکات
|
|
463
|
+
|
|
464
|
+
- `content` میتواند HTML باشد (`<ul>`، mention و …). نوار ریپلای آن را به متن ساده تبدیل میکند.
|
|
465
|
+
- منوی `...` فقط UI پیشفرض است، نه تمپلیت سفارشی.
|
|
466
|
+
- روی دستگاههای touch، سه نقطه همیشه دیده میشود.
|
|
467
|
+
- `appendReply` / `updateItem` / `removeItem` درخت **لودشده** را عوض میکنند؛ منبع lazy را خودتان هم بهروز کنید.
|
|
468
|
+
- ارتفاع ادیتور: `[initialLine]="n"` روی `ax-text-editor`.
|