@douyinfe/semi-foundation 2.92.2 → 2.93.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.
@@ -185,6 +185,39 @@ export default class DialogueFoundation <P = Record<string, any>, S = Record<str
185
185
  this.animation.start();
186
186
  }
187
187
 
188
+ scrollToTopImmediately = () => {
189
+ const element = this._adapter.getContainerRef();
190
+ if (element) {
191
+ element.scrollTop = 0;
192
+ }
193
+ }
194
+
195
+ scrollToTopWithAnimation = () => {
196
+ const duration = strings.SCROLL_ANIMATION_TIME;
197
+ const element = this._adapter.getContainerRef();
198
+ if (!element) {
199
+ return;
200
+ }
201
+ const from = element.scrollTop;
202
+ const to = 0;
203
+ this.animation = new Animation(
204
+ {
205
+ from: { scrollTop: from },
206
+ to: { scrollTop: to },
207
+ },
208
+ {
209
+ duration,
210
+ easing: 'easeInOutCubic'
211
+ }
212
+ );
213
+
214
+ this.animation.on('frame', ({ scrollTop }: { scrollTop: number }) => {
215
+ element.scrollTop = scrollTop;
216
+ });
217
+
218
+ this.animation.start();
219
+ }
220
+
188
221
  containerScroll = (e: any) => {
189
222
  this._persistEvent(e);
190
223
  const update = () => {
@@ -505,6 +505,20 @@ $module: #{$prefix}-aiChatInput;
505
505
  height: 0;
506
506
  pointer-events: none;
507
507
  }
508
+
509
+ // 当段落包含 skillSlot 时,用 ::after 让 placeholder 显示在 skill 后方
510
+ p.has-skill-slot.is-editor-empty:first-child::before {
511
+ content: none;
512
+ }
513
+
514
+ p.has-skill-slot.is-editor-empty:first-child::after {
515
+ color: var(--semi-color-text-2);
516
+ content: attr(data-placeholder);
517
+ display: inline;
518
+ height: 0;
519
+ margin-left: $spacing-aiChatInput_skill_item-columnGap;
520
+ pointer-events: none;
521
+ }
508
522
 
509
523
  p {
510
524
  margin: 0px;
@@ -229,4 +229,56 @@ $module: #{$prefix}-input;
229
229
 
230
230
  }
231
231
 
232
+ // Line number styles
233
+ .#{$module}-textarea-wrapper-withLineNumber {
234
+ display: flex;
235
+ padding: 0;
236
+ align-items: flex-start;
237
+
238
+ .#{$module}-textarea-lineNumber {
239
+ flex-shrink: 0;
240
+ padding: $spacing-textarea-paddingY $spacing-textarea-paddingX;
241
+ background-color: var(--semi-color-fill-1);
242
+ border-right: 1px solid var(--semi-color-border);
243
+ color: var(--semi-color-text-2);
244
+ // Use common monospace font stack for better alignment
245
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
246
+ font-size: inherit;
247
+ line-height: 1.5;
248
+ text-align: right;
249
+ user-select: none;
250
+ min-width: 36px;
251
+ border-radius: $radius-input_wrapper 0 0 $radius-input_wrapper;
252
+ // Allow scrolling but hide scrollbar
253
+ overflow-y: auto;
254
+ overflow-x: hidden;
255
+ scrollbar-width: none; // Firefox
256
+ -ms-overflow-style: none; // IE 10+
257
+ &::-webkit-scrollbar {
258
+ display: none; // Chrome, Safari, Edge
259
+ }
260
+ }
261
+
262
+ // Content wrapper for textarea to participate in flex layout
263
+ .#{$module}-textarea-content {
264
+ display: flex;
265
+ flex: 1;
266
+ min-width: 0;
267
+ }
268
+
269
+ .#{$module}-textarea-lineNumber-item {
270
+ display: flex;
271
+ // Align to the first visual line when soft-wrapping
272
+ align-items: flex-start;
273
+ justify-content: flex-end;
274
+ box-sizing: border-box;
275
+ }
276
+
277
+ .#{$module}-textarea {
278
+ border-radius: 0 $radius-input_wrapper $radius-input_wrapper 0;
279
+ line-height: 1.5;
280
+ flex: 1;
281
+ }
282
+ }
283
+
232
284
  @import "./rtl.scss";
@@ -35,6 +35,8 @@ export default class DialogueFoundation<P = Record<string, any>, S = Record<stri
35
35
  onHintClick: (hint: string) => void;
36
36
  scrollToBottomImmediately: () => void;
37
37
  scrollToBottomWithAnimation: () => void;
38
+ scrollToTopImmediately: () => void;
39
+ scrollToTopWithAnimation: () => void;
38
40
  containerScroll: (e: any) => void;
39
41
  getScroll: import("lodash").DebouncedFunc<(target: any) => typeof scroll>;
40
42
  }
@@ -175,6 +175,39 @@ class DialogueFoundation extends _foundation.default {
175
175
  });
176
176
  this.animation.start();
177
177
  };
178
+ this.scrollToTopImmediately = () => {
179
+ const element = this._adapter.getContainerRef();
180
+ if (element) {
181
+ element.scrollTop = 0;
182
+ }
183
+ };
184
+ this.scrollToTopWithAnimation = () => {
185
+ const duration = _constants.strings.SCROLL_ANIMATION_TIME;
186
+ const element = this._adapter.getContainerRef();
187
+ if (!element) {
188
+ return;
189
+ }
190
+ const from = element.scrollTop;
191
+ const to = 0;
192
+ this.animation = new _semiAnimation.Animation({
193
+ from: {
194
+ scrollTop: from
195
+ },
196
+ to: {
197
+ scrollTop: to
198
+ }
199
+ }, {
200
+ duration,
201
+ easing: 'easeInOutCubic'
202
+ });
203
+ this.animation.on('frame', _ref2 => {
204
+ let {
205
+ scrollTop
206
+ } = _ref2;
207
+ element.scrollTop = scrollTop;
208
+ });
209
+ this.animation.start();
210
+ };
178
211
  this.containerScroll = e => {
179
212
  this._persistEvent(e);
180
213
  const update = () => {
@@ -414,6 +414,17 @@
414
414
  height: 0;
415
415
  pointer-events: none;
416
416
  }
417
+ .semi-aiChatInput-editor-content .tiptap p.has-skill-slot.is-editor-empty:first-child::before {
418
+ content: none;
419
+ }
420
+ .semi-aiChatInput-editor-content .tiptap p.has-skill-slot.is-editor-empty:first-child::after {
421
+ color: var(--semi-color-text-2);
422
+ content: attr(data-placeholder);
423
+ display: inline;
424
+ height: 0;
425
+ margin-left: 8px;
426
+ pointer-events: none;
427
+ }
417
428
  .semi-aiChatInput-editor-content .tiptap p {
418
429
  margin: 0px;
419
430
  white-space: pre-wrap;
@@ -505,6 +505,20 @@ $module: #{$prefix}-aiChatInput;
505
505
  height: 0;
506
506
  pointer-events: none;
507
507
  }
508
+
509
+ // 当段落包含 skillSlot 时,用 ::after 让 placeholder 显示在 skill 后方
510
+ p.has-skill-slot.is-editor-empty:first-child::before {
511
+ content: none;
512
+ }
513
+
514
+ p.has-skill-slot.is-editor-empty:first-child::after {
515
+ color: var(--semi-color-text-2);
516
+ content: attr(data-placeholder);
517
+ display: inline;
518
+ height: 0;
519
+ margin-left: $spacing-aiChatInput_skill_item-columnGap;
520
+ pointer-events: none;
521
+ }
508
522
 
509
523
  p {
510
524
  margin: 0px;
@@ -171,6 +171,49 @@
171
171
  color: var(--semi-color-warning);
172
172
  }
173
173
 
174
+ .semi-input-textarea-wrapper-withLineNumber {
175
+ display: flex;
176
+ padding: 0;
177
+ align-items: flex-start;
178
+ }
179
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-lineNumber {
180
+ flex-shrink: 0;
181
+ padding: 5px 12px;
182
+ background-color: var(--semi-color-fill-1);
183
+ border-right: 1px solid var(--semi-color-border);
184
+ color: var(--semi-color-text-2);
185
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
186
+ font-size: inherit;
187
+ line-height: 1.5;
188
+ text-align: right;
189
+ user-select: none;
190
+ min-width: 36px;
191
+ border-radius: var(--semi-border-radius-small) 0 0 var(--semi-border-radius-small);
192
+ overflow-y: auto;
193
+ overflow-x: hidden;
194
+ scrollbar-width: none;
195
+ -ms-overflow-style: none;
196
+ }
197
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-lineNumber::-webkit-scrollbar {
198
+ display: none;
199
+ }
200
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-content {
201
+ display: flex;
202
+ flex: 1;
203
+ min-width: 0;
204
+ }
205
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-lineNumber-item {
206
+ display: flex;
207
+ align-items: flex-start;
208
+ justify-content: flex-end;
209
+ box-sizing: border-box;
210
+ }
211
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea {
212
+ border-radius: 0 var(--semi-border-radius-small) var(--semi-border-radius-small) 0;
213
+ line-height: 1.5;
214
+ flex: 1;
215
+ }
216
+
174
217
  .semi-rtl .semi-input-wrapper,
175
218
  .semi-portal-rtl .semi-input-wrapper {
176
219
  direction: rtl;
@@ -229,4 +229,56 @@ $module: #{$prefix}-input;
229
229
 
230
230
  }
231
231
 
232
+ // Line number styles
233
+ .#{$module}-textarea-wrapper-withLineNumber {
234
+ display: flex;
235
+ padding: 0;
236
+ align-items: flex-start;
237
+
238
+ .#{$module}-textarea-lineNumber {
239
+ flex-shrink: 0;
240
+ padding: $spacing-textarea-paddingY $spacing-textarea-paddingX;
241
+ background-color: var(--semi-color-fill-1);
242
+ border-right: 1px solid var(--semi-color-border);
243
+ color: var(--semi-color-text-2);
244
+ // Use common monospace font stack for better alignment
245
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
246
+ font-size: inherit;
247
+ line-height: 1.5;
248
+ text-align: right;
249
+ user-select: none;
250
+ min-width: 36px;
251
+ border-radius: $radius-input_wrapper 0 0 $radius-input_wrapper;
252
+ // Allow scrolling but hide scrollbar
253
+ overflow-y: auto;
254
+ overflow-x: hidden;
255
+ scrollbar-width: none; // Firefox
256
+ -ms-overflow-style: none; // IE 10+
257
+ &::-webkit-scrollbar {
258
+ display: none; // Chrome, Safari, Edge
259
+ }
260
+ }
261
+
262
+ // Content wrapper for textarea to participate in flex layout
263
+ .#{$module}-textarea-content {
264
+ display: flex;
265
+ flex: 1;
266
+ min-width: 0;
267
+ }
268
+
269
+ .#{$module}-textarea-lineNumber-item {
270
+ display: flex;
271
+ // Align to the first visual line when soft-wrapping
272
+ align-items: flex-start;
273
+ justify-content: flex-end;
274
+ box-sizing: border-box;
275
+ }
276
+
277
+ .#{$module}-textarea {
278
+ border-radius: 0 $radius-input_wrapper $radius-input_wrapper 0;
279
+ line-height: 1.5;
280
+ flex: 1;
281
+ }
282
+ }
283
+
232
284
  @import "./rtl.scss";
@@ -35,6 +35,8 @@ export default class DialogueFoundation<P = Record<string, any>, S = Record<stri
35
35
  onHintClick: (hint: string) => void;
36
36
  scrollToBottomImmediately: () => void;
37
37
  scrollToBottomWithAnimation: () => void;
38
+ scrollToTopImmediately: () => void;
39
+ scrollToTopWithAnimation: () => void;
38
40
  containerScroll: (e: any) => void;
39
41
  getScroll: import("lodash").DebouncedFunc<(target: any) => typeof scroll>;
40
42
  }
@@ -168,6 +168,39 @@ export default class DialogueFoundation extends BaseFoundation {
168
168
  });
169
169
  this.animation.start();
170
170
  };
171
+ this.scrollToTopImmediately = () => {
172
+ const element = this._adapter.getContainerRef();
173
+ if (element) {
174
+ element.scrollTop = 0;
175
+ }
176
+ };
177
+ this.scrollToTopWithAnimation = () => {
178
+ const duration = strings.SCROLL_ANIMATION_TIME;
179
+ const element = this._adapter.getContainerRef();
180
+ if (!element) {
181
+ return;
182
+ }
183
+ const from = element.scrollTop;
184
+ const to = 0;
185
+ this.animation = new Animation({
186
+ from: {
187
+ scrollTop: from
188
+ },
189
+ to: {
190
+ scrollTop: to
191
+ }
192
+ }, {
193
+ duration,
194
+ easing: 'easeInOutCubic'
195
+ });
196
+ this.animation.on('frame', _ref2 => {
197
+ let {
198
+ scrollTop
199
+ } = _ref2;
200
+ element.scrollTop = scrollTop;
201
+ });
202
+ this.animation.start();
203
+ };
171
204
  this.containerScroll = e => {
172
205
  this._persistEvent(e);
173
206
  const update = () => {
@@ -414,6 +414,17 @@
414
414
  height: 0;
415
415
  pointer-events: none;
416
416
  }
417
+ .semi-aiChatInput-editor-content .tiptap p.has-skill-slot.is-editor-empty:first-child::before {
418
+ content: none;
419
+ }
420
+ .semi-aiChatInput-editor-content .tiptap p.has-skill-slot.is-editor-empty:first-child::after {
421
+ color: var(--semi-color-text-2);
422
+ content: attr(data-placeholder);
423
+ display: inline;
424
+ height: 0;
425
+ margin-left: 8px;
426
+ pointer-events: none;
427
+ }
417
428
  .semi-aiChatInput-editor-content .tiptap p {
418
429
  margin: 0px;
419
430
  white-space: pre-wrap;
@@ -505,6 +505,20 @@ $module: #{$prefix}-aiChatInput;
505
505
  height: 0;
506
506
  pointer-events: none;
507
507
  }
508
+
509
+ // 当段落包含 skillSlot 时,用 ::after 让 placeholder 显示在 skill 后方
510
+ p.has-skill-slot.is-editor-empty:first-child::before {
511
+ content: none;
512
+ }
513
+
514
+ p.has-skill-slot.is-editor-empty:first-child::after {
515
+ color: var(--semi-color-text-2);
516
+ content: attr(data-placeholder);
517
+ display: inline;
518
+ height: 0;
519
+ margin-left: $spacing-aiChatInput_skill_item-columnGap;
520
+ pointer-events: none;
521
+ }
508
522
 
509
523
  p {
510
524
  margin: 0px;
@@ -171,6 +171,49 @@
171
171
  color: var(--semi-color-warning);
172
172
  }
173
173
 
174
+ .semi-input-textarea-wrapper-withLineNumber {
175
+ display: flex;
176
+ padding: 0;
177
+ align-items: flex-start;
178
+ }
179
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-lineNumber {
180
+ flex-shrink: 0;
181
+ padding: 5px 12px;
182
+ background-color: var(--semi-color-fill-1);
183
+ border-right: 1px solid var(--semi-color-border);
184
+ color: var(--semi-color-text-2);
185
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
186
+ font-size: inherit;
187
+ line-height: 1.5;
188
+ text-align: right;
189
+ user-select: none;
190
+ min-width: 36px;
191
+ border-radius: var(--semi-border-radius-small) 0 0 var(--semi-border-radius-small);
192
+ overflow-y: auto;
193
+ overflow-x: hidden;
194
+ scrollbar-width: none;
195
+ -ms-overflow-style: none;
196
+ }
197
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-lineNumber::-webkit-scrollbar {
198
+ display: none;
199
+ }
200
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-content {
201
+ display: flex;
202
+ flex: 1;
203
+ min-width: 0;
204
+ }
205
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea-lineNumber-item {
206
+ display: flex;
207
+ align-items: flex-start;
208
+ justify-content: flex-end;
209
+ box-sizing: border-box;
210
+ }
211
+ .semi-input-textarea-wrapper-withLineNumber .semi-input-textarea {
212
+ border-radius: 0 var(--semi-border-radius-small) var(--semi-border-radius-small) 0;
213
+ line-height: 1.5;
214
+ flex: 1;
215
+ }
216
+
174
217
  .semi-rtl .semi-input-wrapper,
175
218
  .semi-portal-rtl .semi-input-wrapper {
176
219
  direction: rtl;
@@ -229,4 +229,56 @@ $module: #{$prefix}-input;
229
229
 
230
230
  }
231
231
 
232
+ // Line number styles
233
+ .#{$module}-textarea-wrapper-withLineNumber {
234
+ display: flex;
235
+ padding: 0;
236
+ align-items: flex-start;
237
+
238
+ .#{$module}-textarea-lineNumber {
239
+ flex-shrink: 0;
240
+ padding: $spacing-textarea-paddingY $spacing-textarea-paddingX;
241
+ background-color: var(--semi-color-fill-1);
242
+ border-right: 1px solid var(--semi-color-border);
243
+ color: var(--semi-color-text-2);
244
+ // Use common monospace font stack for better alignment
245
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
246
+ font-size: inherit;
247
+ line-height: 1.5;
248
+ text-align: right;
249
+ user-select: none;
250
+ min-width: 36px;
251
+ border-radius: $radius-input_wrapper 0 0 $radius-input_wrapper;
252
+ // Allow scrolling but hide scrollbar
253
+ overflow-y: auto;
254
+ overflow-x: hidden;
255
+ scrollbar-width: none; // Firefox
256
+ -ms-overflow-style: none; // IE 10+
257
+ &::-webkit-scrollbar {
258
+ display: none; // Chrome, Safari, Edge
259
+ }
260
+ }
261
+
262
+ // Content wrapper for textarea to participate in flex layout
263
+ .#{$module}-textarea-content {
264
+ display: flex;
265
+ flex: 1;
266
+ min-width: 0;
267
+ }
268
+
269
+ .#{$module}-textarea-lineNumber-item {
270
+ display: flex;
271
+ // Align to the first visual line when soft-wrapping
272
+ align-items: flex-start;
273
+ justify-content: flex-end;
274
+ box-sizing: border-box;
275
+ }
276
+
277
+ .#{$module}-textarea {
278
+ border-radius: 0 $radius-input_wrapper $radius-input_wrapper 0;
279
+ line-height: 1.5;
280
+ flex: 1;
281
+ }
282
+ }
283
+
232
284
  @import "./rtl.scss";