@atlaskit/editor-plugin-placeholder 6.6.5 → 6.6.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @atlaskit/editor-plugin-placeholder
2
2
 
3
+ ## 6.6.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`356fd6e2db655`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/356fd6e2db655) -
8
+ [ux] [EDITOR-2469] fixed placeholder getting hidden when user tabs
9
+ - Updated dependencies
10
+
11
+ ## 6.6.6
12
+
13
+ ### Patch Changes
14
+
15
+ - [`58e8dc3afa08d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/58e8dc3afa08d) -
16
+ [ux] [EDITOR-2469] add fade in animation to placeholder on empty paragraph
17
+
3
18
  ## 6.6.5
4
19
 
5
20
  ### Patch Changes
@@ -8,6 +8,7 @@ var _processRawValue = require("@atlaskit/editor-common/process-raw-value");
8
8
  var _utils = require("@atlaskit/editor-common/utils");
9
9
  var _model = require("@atlaskit/editor-prosemirror/model");
10
10
  var _view = require("@atlaskit/editor-prosemirror/view");
11
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
11
12
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
12
13
  var _animation = require("./animation");
13
14
  var _constants = require("./constants");
@@ -15,10 +16,12 @@ function createPlaceholderDecoration(editorState, placeholderText, placeholderPr
15
16
  var pos = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
16
17
  var initialDelayWhenUserTypedAndDeleted = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
17
18
  var placeholderADF = arguments.length > 6 ? arguments[6] : undefined;
19
+ var showOnEmptyParagraph = arguments.length > 7 ? arguments[7] : undefined;
18
20
  var placeholderDecoration = document.createElement('span');
19
21
  var placeholderNodeWithText = placeholderDecoration;
20
22
  placeholderDecoration.setAttribute('data-testid', _constants.placeholderTestId);
21
- placeholderDecoration.className = 'placeholder-decoration';
23
+ var shouldFadeIn = showOnEmptyParagraph && (0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_patch_ga_blockers');
24
+ placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
22
25
  placeholderDecoration.setAttribute('aria-hidden', 'true');
23
26
 
24
27
  // PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
@@ -97,7 +97,8 @@ function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderText, empt
97
97
  placeholderText = _getPlaceholderState.placeholderText,
98
98
  pos = _getPlaceholderState.pos,
99
99
  typedAndDeleted = _getPlaceholderState.typedAndDeleted,
100
- contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF;
100
+ contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF,
101
+ showOnEmptyParagraph = _getPlaceholderState.showOnEmptyParagraph;
101
102
 
102
103
  // Decorations is still called after plugin is destroyed
103
104
  // So we need to make sure decorations is not called if plugin has been destroyed to prevent the placeholder animations' setTimeouts called infinitely
@@ -110,7 +111,7 @@ function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderText, empt
110
111
  var initialDelayWhenUserTypedAndDeleted = typedAndDeleted ? _constants.TYPEWRITER_TYPED_AND_DELETED_DELAY : 0;
111
112
  // contextPlaceholderADF takes precedence over the global placeholderADF
112
113
  var placeholderAdfToUse = contextPlaceholderADF || placeholderADF;
113
- return (0, _decorations.createPlaceholderDecoration)(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse);
114
+ return (0, _decorations.createPlaceholderDecoration)(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse, showOnEmptyParagraph);
114
115
  }
115
116
  return;
116
117
  }
@@ -116,10 +116,12 @@ function createPlaceholderDecoration(editorState, placeholderText, placeholderPr
116
116
  var pos = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
117
117
  var initialDelayWhenUserTypedAndDeleted = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
118
118
  var placeholderADF = arguments.length > 6 ? arguments[6] : undefined;
119
+ var showOnEmptyParagraph = arguments.length > 7 ? arguments[7] : undefined;
119
120
  var placeholderDecoration = document.createElement('span');
120
121
  var placeholderNodeWithText = placeholderDecoration;
121
122
  placeholderDecoration.setAttribute('data-testid', placeholderTestId);
122
- placeholderDecoration.className = 'placeholder-decoration';
123
+ var shouldFadeIn = showOnEmptyParagraph && (0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_patch_ga_blockers');
124
+ placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
123
125
  placeholderDecoration.setAttribute('aria-hidden', 'true');
124
126
 
125
127
  // PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
@@ -280,23 +282,52 @@ function createPlaceHolderStateFrom(_ref5) {
280
282
  from = _editorState$selectio.from,
281
283
  to = _editorState$selectio.to,
282
284
  $to = _editorState$selectio.$to;
283
- if ((defaultPlaceholderText || placeholderADF) && withEmptyParagraph && isEditorFocused && !isInitial && !(0, _utils.isEmptyDocument)(editorState.doc) && from === to && (0, _utils.isEmptyParagraph)($to.parent) && (0, _utils.hasDocAsParent)($to)) {
284
- return showOnEmptyParagraph ? setPlaceHolderState({
285
- placeholderText: defaultPlaceholderText,
286
- pos: to,
287
- placeholderPrompts: placeholderPrompts,
288
- typedAndDeleted: typedAndDeleted,
289
- userHadTyped: userHadTyped,
290
- canShowOnEmptyParagraph: true,
291
- showOnEmptyParagraph: true
292
- }) : emptyPlaceholder({
293
- placeholderText: defaultPlaceholderText,
294
- placeholderPrompts: placeholderPrompts,
295
- userHadTyped: userHadTyped,
296
- canShowOnEmptyParagraph: true,
297
- showOnEmptyParagraph: false,
298
- pos: to
299
- });
285
+ var isOnEmptyParagraphInNonEmptyDoc = (defaultPlaceholderText || placeholderADF) && withEmptyParagraph && !isInitial && !(0, _utils.isEmptyDocument)(editorState.doc) && from === to && (0, _utils.isEmptyParagraph)($to.parent) && (0, _utils.hasDocAsParent)($to);
286
+ if (isOnEmptyParagraphInNonEmptyDoc) {
287
+ if ((0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_patch_ga_blockers')) {
288
+ // If placeholder was already shown, keep it visible even without focus
289
+ // This prevents the placeholder from disappearing when switching browser tabs
290
+ if (showOnEmptyParagraph) {
291
+ return setPlaceHolderState({
292
+ placeholderText: defaultPlaceholderText,
293
+ pos: to,
294
+ placeholderPrompts: placeholderPrompts,
295
+ typedAndDeleted: typedAndDeleted,
296
+ userHadTyped: userHadTyped,
297
+ canShowOnEmptyParagraph: true,
298
+ showOnEmptyParagraph: true
299
+ });
300
+ }
301
+ // Focus is required to start the timeout for showing placeholder
302
+ if (isEditorFocused) {
303
+ return emptyPlaceholder({
304
+ placeholderText: defaultPlaceholderText,
305
+ placeholderPrompts: placeholderPrompts,
306
+ userHadTyped: userHadTyped,
307
+ canShowOnEmptyParagraph: true,
308
+ showOnEmptyParagraph: false,
309
+ pos: to
310
+ });
311
+ }
312
+ } else if (isEditorFocused) {
313
+ // Original behavior: focus is required for both showing and keeping placeholder visible
314
+ return showOnEmptyParagraph ? setPlaceHolderState({
315
+ placeholderText: defaultPlaceholderText,
316
+ pos: to,
317
+ placeholderPrompts: placeholderPrompts,
318
+ typedAndDeleted: typedAndDeleted,
319
+ userHadTyped: userHadTyped,
320
+ canShowOnEmptyParagraph: true,
321
+ showOnEmptyParagraph: true
322
+ }) : emptyPlaceholder({
323
+ placeholderText: defaultPlaceholderText,
324
+ placeholderPrompts: placeholderPrompts,
325
+ userHadTyped: userHadTyped,
326
+ canShowOnEmptyParagraph: true,
327
+ showOnEmptyParagraph: false,
328
+ pos: to
329
+ });
330
+ }
300
331
  }
301
332
  }
302
333
  if (isEditorFocused && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
@@ -500,7 +531,8 @@ function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderText, empt
500
531
  placeholderText = _getPlaceholderState.placeholderText,
501
532
  pos = _getPlaceholderState.pos,
502
533
  typedAndDeleted = _getPlaceholderState.typedAndDeleted,
503
- contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF;
534
+ contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF,
535
+ showOnEmptyParagraph = _getPlaceholderState.showOnEmptyParagraph;
504
536
 
505
537
  // Decorations is still called after plugin is destroyed
506
538
  // So we need to make sure decorations is not called if plugin has been destroyed to prevent the placeholder animations' setTimeouts called infinitely
@@ -513,7 +545,7 @@ function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderText, empt
513
545
  var initialDelayWhenUserTypedAndDeleted = typedAndDeleted ? TYPEWRITER_TYPED_AND_DELETED_DELAY : 0;
514
546
  // contextPlaceholderADF takes precedence over the global placeholderADF
515
547
  var placeholderAdfToUse = contextPlaceholderADF || placeholderADF;
516
- return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse);
548
+ return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse, showOnEmptyParagraph);
517
549
  }
518
550
  return;
519
551
  }
@@ -109,23 +109,52 @@ function createPlaceHolderStateFrom(_ref3) {
109
109
  from = _editorState$selectio.from,
110
110
  to = _editorState$selectio.to,
111
111
  $to = _editorState$selectio.$to;
112
- if ((defaultPlaceholderText || placeholderADF) && withEmptyParagraph && isEditorFocused && !isInitial && !(0, _utils.isEmptyDocument)(editorState.doc) && from === to && (0, _utils.isEmptyParagraph)($to.parent) && (0, _utils.hasDocAsParent)($to)) {
113
- return showOnEmptyParagraph ? setPlaceHolderState({
114
- placeholderText: defaultPlaceholderText,
115
- pos: to,
116
- placeholderPrompts: placeholderPrompts,
117
- typedAndDeleted: typedAndDeleted,
118
- userHadTyped: userHadTyped,
119
- canShowOnEmptyParagraph: true,
120
- showOnEmptyParagraph: true
121
- }) : emptyPlaceholder({
122
- placeholderText: defaultPlaceholderText,
123
- placeholderPrompts: placeholderPrompts,
124
- userHadTyped: userHadTyped,
125
- canShowOnEmptyParagraph: true,
126
- showOnEmptyParagraph: false,
127
- pos: to
128
- });
112
+ var isOnEmptyParagraphInNonEmptyDoc = (defaultPlaceholderText || placeholderADF) && withEmptyParagraph && !isInitial && !(0, _utils.isEmptyDocument)(editorState.doc) && from === to && (0, _utils.isEmptyParagraph)($to.parent) && (0, _utils.hasDocAsParent)($to);
113
+ if (isOnEmptyParagraphInNonEmptyDoc) {
114
+ if ((0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_patch_ga_blockers')) {
115
+ // If placeholder was already shown, keep it visible even without focus
116
+ // This prevents the placeholder from disappearing when switching browser tabs
117
+ if (showOnEmptyParagraph) {
118
+ return setPlaceHolderState({
119
+ placeholderText: defaultPlaceholderText,
120
+ pos: to,
121
+ placeholderPrompts: placeholderPrompts,
122
+ typedAndDeleted: typedAndDeleted,
123
+ userHadTyped: userHadTyped,
124
+ canShowOnEmptyParagraph: true,
125
+ showOnEmptyParagraph: true
126
+ });
127
+ }
128
+ // Focus is required to start the timeout for showing placeholder
129
+ if (isEditorFocused) {
130
+ return emptyPlaceholder({
131
+ placeholderText: defaultPlaceholderText,
132
+ placeholderPrompts: placeholderPrompts,
133
+ userHadTyped: userHadTyped,
134
+ canShowOnEmptyParagraph: true,
135
+ showOnEmptyParagraph: false,
136
+ pos: to
137
+ });
138
+ }
139
+ } else if (isEditorFocused) {
140
+ // Original behavior: focus is required for both showing and keeping placeholder visible
141
+ return showOnEmptyParagraph ? setPlaceHolderState({
142
+ placeholderText: defaultPlaceholderText,
143
+ pos: to,
144
+ placeholderPrompts: placeholderPrompts,
145
+ typedAndDeleted: typedAndDeleted,
146
+ userHadTyped: userHadTyped,
147
+ canShowOnEmptyParagraph: true,
148
+ showOnEmptyParagraph: true
149
+ }) : emptyPlaceholder({
150
+ placeholderText: defaultPlaceholderText,
151
+ placeholderPrompts: placeholderPrompts,
152
+ userHadTyped: userHadTyped,
153
+ canShowOnEmptyParagraph: true,
154
+ showOnEmptyParagraph: false,
155
+ pos: to
156
+ });
157
+ }
129
158
  }
130
159
  }
131
160
  if (isEditorFocused && (0, _experiments.editorExperiment)('platform_editor_controls', 'variant1')) {
@@ -2,14 +2,16 @@ import { processRawValue } from '@atlaskit/editor-common/process-raw-value';
2
2
  import { browser } from '@atlaskit/editor-common/utils';
3
3
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
4
4
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
5
6
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
6
7
  import { cycleThroughPlaceholderPrompts } from './animation';
7
8
  import { placeholderTestId } from './constants';
8
- export function createPlaceholderDecoration(editorState, placeholderText, placeholderPrompts, activeTypewriterTimeouts, pos = 1, initialDelayWhenUserTypedAndDeleted = 0, placeholderADF) {
9
+ export function createPlaceholderDecoration(editorState, placeholderText, placeholderPrompts, activeTypewriterTimeouts, pos = 1, initialDelayWhenUserTypedAndDeleted = 0, placeholderADF, showOnEmptyParagraph) {
9
10
  const placeholderDecoration = document.createElement('span');
10
11
  let placeholderNodeWithText = placeholderDecoration;
11
12
  placeholderDecoration.setAttribute('data-testid', placeholderTestId);
12
- placeholderDecoration.className = 'placeholder-decoration';
13
+ const shouldFadeIn = showOnEmptyParagraph && fg('platform_editor_ai_aifc_patch_ga_blockers');
14
+ placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
13
15
  placeholderDecoration.setAttribute('aria-hidden', 'true');
14
16
 
15
17
  // PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
@@ -90,7 +90,8 @@ export default function createPlugin(intl, defaultPlaceholderText, bracketPlaceh
90
90
  placeholderText,
91
91
  pos,
92
92
  typedAndDeleted,
93
- contextPlaceholderADF
93
+ contextPlaceholderADF,
94
+ showOnEmptyParagraph
94
95
  } = getPlaceholderState(editorState);
95
96
 
96
97
  // Decorations is still called after plugin is destroyed
@@ -104,7 +105,7 @@ export default function createPlugin(intl, defaultPlaceholderText, bracketPlaceh
104
105
  const initialDelayWhenUserTypedAndDeleted = typedAndDeleted ? TYPEWRITER_TYPED_AND_DELETED_DELAY : 0;
105
106
  // contextPlaceholderADF takes precedence over the global placeholderADF
106
107
  const placeholderAdfToUse = contextPlaceholderADF || placeholderADF;
107
- return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse);
108
+ return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse, showOnEmptyParagraph);
108
109
  }
109
110
  return;
110
111
  }
@@ -94,11 +94,12 @@ const cycleThroughPlaceholderPrompts = (placeholderPrompts, activeTypewriterTime
94
94
  startAnimationCycle();
95
95
  }
96
96
  };
97
- export function createPlaceholderDecoration(editorState, placeholderText, placeholderPrompts, activeTypewriterTimeouts, pos = 1, initialDelayWhenUserTypedAndDeleted = 0, placeholderADF) {
97
+ export function createPlaceholderDecoration(editorState, placeholderText, placeholderPrompts, activeTypewriterTimeouts, pos = 1, initialDelayWhenUserTypedAndDeleted = 0, placeholderADF, showOnEmptyParagraph) {
98
98
  const placeholderDecoration = document.createElement('span');
99
99
  let placeholderNodeWithText = placeholderDecoration;
100
100
  placeholderDecoration.setAttribute('data-testid', placeholderTestId);
101
- placeholderDecoration.className = 'placeholder-decoration';
101
+ const shouldFadeIn = showOnEmptyParagraph && fg('platform_editor_ai_aifc_patch_ga_blockers');
102
+ placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
102
103
  placeholderDecoration.setAttribute('aria-hidden', 'true');
103
104
 
104
105
  // PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
@@ -262,23 +263,52 @@ function createPlaceHolderStateFrom({
262
263
  to,
263
264
  $to
264
265
  } = editorState.selection;
265
- if ((defaultPlaceholderText || placeholderADF) && withEmptyParagraph && isEditorFocused && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to)) {
266
- return showOnEmptyParagraph ? setPlaceHolderState({
267
- placeholderText: defaultPlaceholderText,
268
- pos: to,
269
- placeholderPrompts,
270
- typedAndDeleted,
271
- userHadTyped,
272
- canShowOnEmptyParagraph: true,
273
- showOnEmptyParagraph: true
274
- }) : emptyPlaceholder({
275
- placeholderText: defaultPlaceholderText,
276
- placeholderPrompts,
277
- userHadTyped,
278
- canShowOnEmptyParagraph: true,
279
- showOnEmptyParagraph: false,
280
- pos: to
281
- });
266
+ const isOnEmptyParagraphInNonEmptyDoc = (defaultPlaceholderText || placeholderADF) && withEmptyParagraph && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to);
267
+ if (isOnEmptyParagraphInNonEmptyDoc) {
268
+ if (fg('platform_editor_ai_aifc_patch_ga_blockers')) {
269
+ // If placeholder was already shown, keep it visible even without focus
270
+ // This prevents the placeholder from disappearing when switching browser tabs
271
+ if (showOnEmptyParagraph) {
272
+ return setPlaceHolderState({
273
+ placeholderText: defaultPlaceholderText,
274
+ pos: to,
275
+ placeholderPrompts,
276
+ typedAndDeleted,
277
+ userHadTyped,
278
+ canShowOnEmptyParagraph: true,
279
+ showOnEmptyParagraph: true
280
+ });
281
+ }
282
+ // Focus is required to start the timeout for showing placeholder
283
+ if (isEditorFocused) {
284
+ return emptyPlaceholder({
285
+ placeholderText: defaultPlaceholderText,
286
+ placeholderPrompts,
287
+ userHadTyped,
288
+ canShowOnEmptyParagraph: true,
289
+ showOnEmptyParagraph: false,
290
+ pos: to
291
+ });
292
+ }
293
+ } else if (isEditorFocused) {
294
+ // Original behavior: focus is required for both showing and keeping placeholder visible
295
+ return showOnEmptyParagraph ? setPlaceHolderState({
296
+ placeholderText: defaultPlaceholderText,
297
+ pos: to,
298
+ placeholderPrompts,
299
+ typedAndDeleted,
300
+ userHadTyped,
301
+ canShowOnEmptyParagraph: true,
302
+ showOnEmptyParagraph: true
303
+ }) : emptyPlaceholder({
304
+ placeholderText: defaultPlaceholderText,
305
+ placeholderPrompts,
306
+ userHadTyped,
307
+ canShowOnEmptyParagraph: true,
308
+ showOnEmptyParagraph: false,
309
+ pos: to
310
+ });
311
+ }
282
312
  }
283
313
  }
284
314
  if (isEditorFocused && editorExperiment('platform_editor_controls', 'variant1')) {
@@ -483,7 +513,8 @@ export function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderTex
483
513
  placeholderText,
484
514
  pos,
485
515
  typedAndDeleted,
486
- contextPlaceholderADF
516
+ contextPlaceholderADF,
517
+ showOnEmptyParagraph
487
518
  } = getPlaceholderState(editorState);
488
519
 
489
520
  // Decorations is still called after plugin is destroyed
@@ -497,7 +528,7 @@ export function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderTex
497
528
  const initialDelayWhenUserTypedAndDeleted = typedAndDeleted ? TYPEWRITER_TYPED_AND_DELETED_DELAY : 0;
498
529
  // contextPlaceholderADF takes precedence over the global placeholderADF
499
530
  const placeholderAdfToUse = contextPlaceholderADF || placeholderADF;
500
- return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse);
531
+ return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse, showOnEmptyParagraph);
501
532
  }
502
533
  return;
503
534
  }
@@ -98,23 +98,52 @@ export function createPlaceHolderStateFrom({
98
98
  to,
99
99
  $to
100
100
  } = editorState.selection;
101
- if ((defaultPlaceholderText || placeholderADF) && withEmptyParagraph && isEditorFocused && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to)) {
102
- return showOnEmptyParagraph ? setPlaceHolderState({
103
- placeholderText: defaultPlaceholderText,
104
- pos: to,
105
- placeholderPrompts,
106
- typedAndDeleted,
107
- userHadTyped,
108
- canShowOnEmptyParagraph: true,
109
- showOnEmptyParagraph: true
110
- }) : emptyPlaceholder({
111
- placeholderText: defaultPlaceholderText,
112
- placeholderPrompts,
113
- userHadTyped,
114
- canShowOnEmptyParagraph: true,
115
- showOnEmptyParagraph: false,
116
- pos: to
117
- });
101
+ const isOnEmptyParagraphInNonEmptyDoc = (defaultPlaceholderText || placeholderADF) && withEmptyParagraph && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to);
102
+ if (isOnEmptyParagraphInNonEmptyDoc) {
103
+ if (fg('platform_editor_ai_aifc_patch_ga_blockers')) {
104
+ // If placeholder was already shown, keep it visible even without focus
105
+ // This prevents the placeholder from disappearing when switching browser tabs
106
+ if (showOnEmptyParagraph) {
107
+ return setPlaceHolderState({
108
+ placeholderText: defaultPlaceholderText,
109
+ pos: to,
110
+ placeholderPrompts,
111
+ typedAndDeleted,
112
+ userHadTyped,
113
+ canShowOnEmptyParagraph: true,
114
+ showOnEmptyParagraph: true
115
+ });
116
+ }
117
+ // Focus is required to start the timeout for showing placeholder
118
+ if (isEditorFocused) {
119
+ return emptyPlaceholder({
120
+ placeholderText: defaultPlaceholderText,
121
+ placeholderPrompts,
122
+ userHadTyped,
123
+ canShowOnEmptyParagraph: true,
124
+ showOnEmptyParagraph: false,
125
+ pos: to
126
+ });
127
+ }
128
+ } else if (isEditorFocused) {
129
+ // Original behavior: focus is required for both showing and keeping placeholder visible
130
+ return showOnEmptyParagraph ? setPlaceHolderState({
131
+ placeholderText: defaultPlaceholderText,
132
+ pos: to,
133
+ placeholderPrompts,
134
+ typedAndDeleted,
135
+ userHadTyped,
136
+ canShowOnEmptyParagraph: true,
137
+ showOnEmptyParagraph: true
138
+ }) : emptyPlaceholder({
139
+ placeholderText: defaultPlaceholderText,
140
+ placeholderPrompts,
141
+ userHadTyped,
142
+ canShowOnEmptyParagraph: true,
143
+ showOnEmptyParagraph: false,
144
+ pos: to
145
+ });
146
+ }
118
147
  }
119
148
  }
120
149
  if (isEditorFocused && editorExperiment('platform_editor_controls', 'variant1')) {
@@ -2,6 +2,7 @@ import { processRawValue } from '@atlaskit/editor-common/process-raw-value';
2
2
  import { browser } from '@atlaskit/editor-common/utils';
3
3
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
4
4
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
5
6
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
6
7
  import { cycleThroughPlaceholderPrompts } from './animation';
7
8
  import { placeholderTestId } from './constants';
@@ -9,10 +10,12 @@ export function createPlaceholderDecoration(editorState, placeholderText, placeh
9
10
  var pos = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
10
11
  var initialDelayWhenUserTypedAndDeleted = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
11
12
  var placeholderADF = arguments.length > 6 ? arguments[6] : undefined;
13
+ var showOnEmptyParagraph = arguments.length > 7 ? arguments[7] : undefined;
12
14
  var placeholderDecoration = document.createElement('span');
13
15
  var placeholderNodeWithText = placeholderDecoration;
14
16
  placeholderDecoration.setAttribute('data-testid', placeholderTestId);
15
- placeholderDecoration.className = 'placeholder-decoration';
17
+ var shouldFadeIn = showOnEmptyParagraph && fg('platform_editor_ai_aifc_patch_ga_blockers');
18
+ placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
16
19
  placeholderDecoration.setAttribute('aria-hidden', 'true');
17
20
 
18
21
  // PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
@@ -91,7 +91,8 @@ export default function createPlugin(intl, defaultPlaceholderText, bracketPlaceh
91
91
  placeholderText = _getPlaceholderState.placeholderText,
92
92
  pos = _getPlaceholderState.pos,
93
93
  typedAndDeleted = _getPlaceholderState.typedAndDeleted,
94
- contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF;
94
+ contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF,
95
+ showOnEmptyParagraph = _getPlaceholderState.showOnEmptyParagraph;
95
96
 
96
97
  // Decorations is still called after plugin is destroyed
97
98
  // So we need to make sure decorations is not called if plugin has been destroyed to prevent the placeholder animations' setTimeouts called infinitely
@@ -104,7 +105,7 @@ export default function createPlugin(intl, defaultPlaceholderText, bracketPlaceh
104
105
  var initialDelayWhenUserTypedAndDeleted = typedAndDeleted ? TYPEWRITER_TYPED_AND_DELETED_DELAY : 0;
105
106
  // contextPlaceholderADF takes precedence over the global placeholderADF
106
107
  var placeholderAdfToUse = contextPlaceholderADF || placeholderADF;
107
- return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse);
108
+ return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse, showOnEmptyParagraph);
108
109
  }
109
110
  return;
110
111
  }
@@ -106,10 +106,12 @@ export function createPlaceholderDecoration(editorState, placeholderText, placeh
106
106
  var pos = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
107
107
  var initialDelayWhenUserTypedAndDeleted = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
108
108
  var placeholderADF = arguments.length > 6 ? arguments[6] : undefined;
109
+ var showOnEmptyParagraph = arguments.length > 7 ? arguments[7] : undefined;
109
110
  var placeholderDecoration = document.createElement('span');
110
111
  var placeholderNodeWithText = placeholderDecoration;
111
112
  placeholderDecoration.setAttribute('data-testid', placeholderTestId);
112
- placeholderDecoration.className = 'placeholder-decoration';
113
+ var shouldFadeIn = showOnEmptyParagraph && fg('platform_editor_ai_aifc_patch_ga_blockers');
114
+ placeholderDecoration.className = shouldFadeIn ? 'placeholder-decoration placeholder-decoration-fade-in' : 'placeholder-decoration';
113
115
  placeholderDecoration.setAttribute('aria-hidden', 'true');
114
116
 
115
117
  // PM sets contenteditable to false on Decorations so Firefox doesn't display the flashing cursor
@@ -270,23 +272,52 @@ function createPlaceHolderStateFrom(_ref5) {
270
272
  from = _editorState$selectio.from,
271
273
  to = _editorState$selectio.to,
272
274
  $to = _editorState$selectio.$to;
273
- if ((defaultPlaceholderText || placeholderADF) && withEmptyParagraph && isEditorFocused && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to)) {
274
- return showOnEmptyParagraph ? setPlaceHolderState({
275
- placeholderText: defaultPlaceholderText,
276
- pos: to,
277
- placeholderPrompts: placeholderPrompts,
278
- typedAndDeleted: typedAndDeleted,
279
- userHadTyped: userHadTyped,
280
- canShowOnEmptyParagraph: true,
281
- showOnEmptyParagraph: true
282
- }) : emptyPlaceholder({
283
- placeholderText: defaultPlaceholderText,
284
- placeholderPrompts: placeholderPrompts,
285
- userHadTyped: userHadTyped,
286
- canShowOnEmptyParagraph: true,
287
- showOnEmptyParagraph: false,
288
- pos: to
289
- });
275
+ var isOnEmptyParagraphInNonEmptyDoc = (defaultPlaceholderText || placeholderADF) && withEmptyParagraph && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to);
276
+ if (isOnEmptyParagraphInNonEmptyDoc) {
277
+ if (fg('platform_editor_ai_aifc_patch_ga_blockers')) {
278
+ // If placeholder was already shown, keep it visible even without focus
279
+ // This prevents the placeholder from disappearing when switching browser tabs
280
+ if (showOnEmptyParagraph) {
281
+ return setPlaceHolderState({
282
+ placeholderText: defaultPlaceholderText,
283
+ pos: to,
284
+ placeholderPrompts: placeholderPrompts,
285
+ typedAndDeleted: typedAndDeleted,
286
+ userHadTyped: userHadTyped,
287
+ canShowOnEmptyParagraph: true,
288
+ showOnEmptyParagraph: true
289
+ });
290
+ }
291
+ // Focus is required to start the timeout for showing placeholder
292
+ if (isEditorFocused) {
293
+ return emptyPlaceholder({
294
+ placeholderText: defaultPlaceholderText,
295
+ placeholderPrompts: placeholderPrompts,
296
+ userHadTyped: userHadTyped,
297
+ canShowOnEmptyParagraph: true,
298
+ showOnEmptyParagraph: false,
299
+ pos: to
300
+ });
301
+ }
302
+ } else if (isEditorFocused) {
303
+ // Original behavior: focus is required for both showing and keeping placeholder visible
304
+ return showOnEmptyParagraph ? setPlaceHolderState({
305
+ placeholderText: defaultPlaceholderText,
306
+ pos: to,
307
+ placeholderPrompts: placeholderPrompts,
308
+ typedAndDeleted: typedAndDeleted,
309
+ userHadTyped: userHadTyped,
310
+ canShowOnEmptyParagraph: true,
311
+ showOnEmptyParagraph: true
312
+ }) : emptyPlaceholder({
313
+ placeholderText: defaultPlaceholderText,
314
+ placeholderPrompts: placeholderPrompts,
315
+ userHadTyped: userHadTyped,
316
+ canShowOnEmptyParagraph: true,
317
+ showOnEmptyParagraph: false,
318
+ pos: to
319
+ });
320
+ }
290
321
  }
291
322
  }
292
323
  if (isEditorFocused && editorExperiment('platform_editor_controls', 'variant1')) {
@@ -490,7 +521,8 @@ export function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderTex
490
521
  placeholderText = _getPlaceholderState.placeholderText,
491
522
  pos = _getPlaceholderState.pos,
492
523
  typedAndDeleted = _getPlaceholderState.typedAndDeleted,
493
- contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF;
524
+ contextPlaceholderADF = _getPlaceholderState.contextPlaceholderADF,
525
+ showOnEmptyParagraph = _getPlaceholderState.showOnEmptyParagraph;
494
526
 
495
527
  // Decorations is still called after plugin is destroyed
496
528
  // So we need to make sure decorations is not called if plugin has been destroyed to prevent the placeholder animations' setTimeouts called infinitely
@@ -503,7 +535,7 @@ export function createPlugin(intl, defaultPlaceholderText, bracketPlaceholderTex
503
535
  var initialDelayWhenUserTypedAndDeleted = typedAndDeleted ? TYPEWRITER_TYPED_AND_DELETED_DELAY : 0;
504
536
  // contextPlaceholderADF takes precedence over the global placeholderADF
505
537
  var placeholderAdfToUse = contextPlaceholderADF || placeholderADF;
506
- return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse);
538
+ return createPlaceholderDecoration(editorState, placeholderText !== null && placeholderText !== void 0 ? placeholderText : '', placeholderPrompts, activeTypewriterTimeouts, pos, initialDelayWhenUserTypedAndDeleted, placeholderAdfToUse, showOnEmptyParagraph);
507
539
  }
508
540
  return;
509
541
  }
@@ -98,23 +98,52 @@ export function createPlaceHolderStateFrom(_ref3) {
98
98
  from = _editorState$selectio.from,
99
99
  to = _editorState$selectio.to,
100
100
  $to = _editorState$selectio.$to;
101
- if ((defaultPlaceholderText || placeholderADF) && withEmptyParagraph && isEditorFocused && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to)) {
102
- return showOnEmptyParagraph ? setPlaceHolderState({
103
- placeholderText: defaultPlaceholderText,
104
- pos: to,
105
- placeholderPrompts: placeholderPrompts,
106
- typedAndDeleted: typedAndDeleted,
107
- userHadTyped: userHadTyped,
108
- canShowOnEmptyParagraph: true,
109
- showOnEmptyParagraph: true
110
- }) : emptyPlaceholder({
111
- placeholderText: defaultPlaceholderText,
112
- placeholderPrompts: placeholderPrompts,
113
- userHadTyped: userHadTyped,
114
- canShowOnEmptyParagraph: true,
115
- showOnEmptyParagraph: false,
116
- pos: to
117
- });
101
+ var isOnEmptyParagraphInNonEmptyDoc = (defaultPlaceholderText || placeholderADF) && withEmptyParagraph && !isInitial && !isEmptyDocument(editorState.doc) && from === to && isEmptyParagraph($to.parent) && hasDocAsParent($to);
102
+ if (isOnEmptyParagraphInNonEmptyDoc) {
103
+ if (fg('platform_editor_ai_aifc_patch_ga_blockers')) {
104
+ // If placeholder was already shown, keep it visible even without focus
105
+ // This prevents the placeholder from disappearing when switching browser tabs
106
+ if (showOnEmptyParagraph) {
107
+ return setPlaceHolderState({
108
+ placeholderText: defaultPlaceholderText,
109
+ pos: to,
110
+ placeholderPrompts: placeholderPrompts,
111
+ typedAndDeleted: typedAndDeleted,
112
+ userHadTyped: userHadTyped,
113
+ canShowOnEmptyParagraph: true,
114
+ showOnEmptyParagraph: true
115
+ });
116
+ }
117
+ // Focus is required to start the timeout for showing placeholder
118
+ if (isEditorFocused) {
119
+ return emptyPlaceholder({
120
+ placeholderText: defaultPlaceholderText,
121
+ placeholderPrompts: placeholderPrompts,
122
+ userHadTyped: userHadTyped,
123
+ canShowOnEmptyParagraph: true,
124
+ showOnEmptyParagraph: false,
125
+ pos: to
126
+ });
127
+ }
128
+ } else if (isEditorFocused) {
129
+ // Original behavior: focus is required for both showing and keeping placeholder visible
130
+ return showOnEmptyParagraph ? setPlaceHolderState({
131
+ placeholderText: defaultPlaceholderText,
132
+ pos: to,
133
+ placeholderPrompts: placeholderPrompts,
134
+ typedAndDeleted: typedAndDeleted,
135
+ userHadTyped: userHadTyped,
136
+ canShowOnEmptyParagraph: true,
137
+ showOnEmptyParagraph: true
138
+ }) : emptyPlaceholder({
139
+ placeholderText: defaultPlaceholderText,
140
+ placeholderPrompts: placeholderPrompts,
141
+ userHadTyped: userHadTyped,
142
+ canShowOnEmptyParagraph: true,
143
+ showOnEmptyParagraph: false,
144
+ pos: to
145
+ });
146
+ }
118
147
  }
119
148
  }
120
149
  if (isEditorFocused && editorExperiment('platform_editor_controls', 'variant1')) {
@@ -1,4 +1,4 @@
1
1
  import type { DocNode } from '@atlaskit/adf-schema';
2
2
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
3
3
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
- export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode): DecorationSet;
4
+ export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode, showOnEmptyParagraph?: boolean): DecorationSet;
@@ -8,6 +8,6 @@ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import type { PlaceholderPlugin } from '../placeholderPluginType';
9
9
  export declare const EMPTY_PARAGRAPH_TIMEOUT_DELAY = 2000;
10
10
  export declare const pluginKey: PluginKey<any>;
11
- export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode): DecorationSet;
11
+ export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode, showOnEmptyParagraph?: boolean): DecorationSet;
12
12
  export declare function createPlugin(intl: IntlShape, defaultPlaceholderText?: string, bracketPlaceholderText?: string, emptyLinePlaceholder?: string, placeholderPrompts?: string[], withEmptyParagraph?: boolean, placeholderADF?: DocNode, api?: ExtractInjectionAPI<PlaceholderPlugin>): SafePlugin | undefined;
13
13
  export declare const placeholderPluginLegacy: PlaceholderPlugin;
@@ -1,4 +1,4 @@
1
1
  import type { DocNode } from '@atlaskit/adf-schema';
2
2
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
3
3
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
- export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode): DecorationSet;
4
+ export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode, showOnEmptyParagraph?: boolean): DecorationSet;
@@ -8,6 +8,6 @@ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
8
  import type { PlaceholderPlugin } from '../placeholderPluginType';
9
9
  export declare const EMPTY_PARAGRAPH_TIMEOUT_DELAY = 2000;
10
10
  export declare const pluginKey: PluginKey<any>;
11
- export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode): DecorationSet;
11
+ export declare function createPlaceholderDecoration(editorState: EditorState, placeholderText: string, placeholderPrompts?: string[], activeTypewriterTimeouts?: (() => void)[], pos?: number, initialDelayWhenUserTypedAndDeleted?: number, placeholderADF?: DocNode, showOnEmptyParagraph?: boolean): DecorationSet;
12
12
  export declare function createPlugin(intl: IntlShape, defaultPlaceholderText?: string, bracketPlaceholderText?: string, emptyLinePlaceholder?: string, placeholderPrompts?: string[], withEmptyParagraph?: boolean, placeholderADF?: DocNode, api?: ExtractInjectionAPI<PlaceholderPlugin>): SafePlugin | undefined;
13
13
  export declare const placeholderPluginLegacy: PlaceholderPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-placeholder",
3
- "version": "6.6.5",
3
+ "version": "6.6.7",
4
4
  "description": "Placeholder plugin for @atlaskit/editor-core.",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -31,15 +31,15 @@
31
31
  "@atlaskit/editor-plugin-composition": "^5.0.0",
32
32
  "@atlaskit/editor-plugin-focus": "^5.0.0",
33
33
  "@atlaskit/editor-plugin-show-diff": "^3.3.0",
34
- "@atlaskit/editor-plugin-type-ahead": "^6.5.0",
34
+ "@atlaskit/editor-plugin-type-ahead": "^6.6.0",
35
35
  "@atlaskit/editor-prosemirror": "^7.2.0",
36
36
  "@atlaskit/platform-feature-flags": "^1.1.0",
37
- "@atlaskit/tmp-editor-statsig": "^16.0.0",
37
+ "@atlaskit/tmp-editor-statsig": "^16.3.0",
38
38
  "@atlaskit/tokens": "^9.0.0",
39
39
  "@babel/runtime": "^7.0.0"
40
40
  },
41
41
  "peerDependencies": {
42
- "@atlaskit/editor-common": "^110.46.0",
42
+ "@atlaskit/editor-common": "^110.49.0",
43
43
  "react": "^18.2.0",
44
44
  "react-dom": "^18.2.0",
45
45
  "react-intl-next": "npm:react-intl@^5.18.1"