@atlaskit/editor-plugin-code-block 12.1.5 → 12.1.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.
Files changed (30) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/editor-commands/index.js +5 -3
  3. package/dist/cjs/pm-plugins/toolbar.js +23 -24
  4. package/dist/cjs/ui/CodeBlockLanguagePicker.js +45 -0
  5. package/dist/cjs/ui/LanguagePicker.js +63 -10
  6. package/dist/cjs/ui/language-picker-options.js +21 -4
  7. package/dist/cjs/ui/recent-languages.js +50 -0
  8. package/dist/es2019/editor-commands/index.js +5 -2
  9. package/dist/es2019/pm-plugins/toolbar.js +168 -167
  10. package/dist/es2019/ui/CodeBlockLanguagePicker.js +31 -0
  11. package/dist/es2019/ui/LanguagePicker.js +41 -9
  12. package/dist/es2019/ui/language-picker-options.js +15 -4
  13. package/dist/es2019/ui/recent-languages.js +38 -0
  14. package/dist/esm/editor-commands/index.js +5 -3
  15. package/dist/esm/pm-plugins/toolbar.js +24 -25
  16. package/dist/esm/ui/CodeBlockLanguagePicker.js +36 -0
  17. package/dist/esm/ui/LanguagePicker.js +64 -11
  18. package/dist/esm/ui/language-picker-options.js +21 -4
  19. package/dist/esm/ui/recent-languages.js +43 -0
  20. package/dist/types/editor-commands/index.d.ts +2 -1
  21. package/dist/types/ui/CodeBlockLanguagePicker.d.ts +5 -0
  22. package/dist/types/ui/LanguagePicker.d.ts +7 -5
  23. package/dist/types/ui/language-picker-options.d.ts +2 -0
  24. package/dist/types/ui/recent-languages.d.ts +4 -0
  25. package/dist/types-ts4.5/editor-commands/index.d.ts +2 -1
  26. package/dist/types-ts4.5/ui/CodeBlockLanguagePicker.d.ts +5 -0
  27. package/dist/types-ts4.5/ui/LanguagePicker.d.ts +7 -5
  28. package/dist/types-ts4.5/ui/language-picker-options.d.ts +2 -0
  29. package/dist/types-ts4.5/ui/recent-languages.d.ts +4 -0
  30. package/package.json +7 -5
@@ -14,9 +14,9 @@ import TextWrapIcon from '@atlaskit/icon/core/text-wrap';
14
14
  import { fg } from '@atlaskit/platform-feature-flags';
15
15
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
16
16
  import { changeLanguage, copyContentToClipboardWithAnalytics, removeCodeBlockWithAnalytics, resetCopiedState, toggleLineNumbersForCodeBlockNode, toggleWordWrapStateForCodeBlockNode } from '../editor-commands';
17
+ import { CodeBlockLanguagePicker } from '../ui/CodeBlockLanguagePicker';
17
18
  import { WrapIcon } from '../ui/icons/WrapIcon';
18
- import { createGroupedLanguageOptions, NONE_LANGUAGE_VALUE, PLAIN_TEXT_LANGUAGE_VALUE } from '../ui/language-picker-options';
19
- import { LanguagePicker } from '../ui/LanguagePicker';
19
+ import { NONE_LANGUAGE_VALUE, PLAIN_TEXT_LANGUAGE_VALUE } from '../ui/language-picker-options';
20
20
  import { provideVisualFeedbackForCopyButton, removeVisualFeedbackForCopyButton } from './codeBlockCopySelectionPlugin';
21
21
  import { createLanguageList, DEFAULT_LANGUAGES, getLanguageIdentifier } from './language-list';
22
22
  import { pluginKey } from './plugin-key';
@@ -24,6 +24,18 @@ export var getToolbarConfig = function getToolbarConfig() {
24
24
  var allowCopyToClipboard = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
25
25
  var api = arguments.length > 1 ? arguments[1] : undefined;
26
26
  var overrideLanguageName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
27
+ var languageList = createLanguageList(overrideLanguageName ? DEFAULT_LANGUAGES.map(function (languageOption) {
28
+ return _objectSpread(_objectSpread({}, languageOption), {}, {
29
+ name: overrideLanguageName(languageOption.name)
30
+ });
31
+ }) : DEFAULT_LANGUAGES);
32
+ var languagePickerOptions = languageList.map(function (lang) {
33
+ return {
34
+ label: lang.name,
35
+ value: getLanguageIdentifier(lang),
36
+ alias: lang.alias
37
+ };
38
+ });
27
39
  return function (state, _ref) {
28
40
  var _api$editorViewMode, _api$decorations$acti, _api$decorations, _api$analytics, _codeBlockState$pos, _node$attrs;
29
41
  var formatMessage = _ref.formatMessage;
@@ -44,23 +56,15 @@ export var getToolbarConfig = function getToolbarConfig() {
44
56
  var isWrapped = isCodeBlockWordWrapEnabled(node);
45
57
  var areLineNumbersVisible = areCodeBlockLineNumbersVisible(node);
46
58
  var language = node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.language;
47
- var languageList = createLanguageList(overrideLanguageName ? DEFAULT_LANGUAGES.map(function (language) {
48
- return _objectSpread(_objectSpread({}, language), {}, {
49
- name: overrideLanguageName(language.name)
50
- });
51
- }) : DEFAULT_LANGUAGES);
52
- var options = languageList.map(function (lang) {
53
- return {
54
- label: lang.name,
55
- value: getLanguageIdentifier(lang),
56
- alias: lang.alias
57
- };
59
+ // Keep fresh option objects for the legacy toolbar select so reopening it
60
+ // continues to start from the top rather than preserving the previously
61
+ // focused option by reference.
62
+ var languageSelectOptions = languagePickerOptions.map(function (option) {
63
+ return _objectSpread({}, option);
58
64
  });
59
-
60
- // If language is not undefined search for it in the value and then search in the aliases
61
- var defaultValue = language ? options.find(function (option) {
65
+ var defaultValue = language ? languageSelectOptions.find(function (option) {
62
66
  return option.value === language;
63
- }) || options.find(function (option) {
67
+ }) || languageSelectOptions.find(function (option) {
64
68
  return option.alias.includes(language);
65
69
  }) : null;
66
70
  var languageSelect = {
@@ -72,16 +76,11 @@ export var getToolbarConfig = function getToolbarConfig() {
72
76
  },
73
77
  defaultValue: defaultValue,
74
78
  placeholder: formatMessage(codeBlockButtonMessages.selectLanguage),
75
- options: options,
79
+ options: languageSelectOptions,
76
80
  filterOption: languageListFilter
77
81
  };
78
82
  var languagePicker;
79
83
  if (expValEquals('platform_editor_code_block_q4_lovability', 'isEnabled', true) && fg('platform_editor_code_block_add_line_number_button')) {
80
- var languagePickerOptions = options;
81
- var groupedOptions = createGroupedLanguageOptions({
82
- formatMessage: formatMessage,
83
- languages: languagePickerOptions
84
- });
85
84
  var defaultPickerValue = language ? languagePickerOptions.find(function (option) {
86
85
  return language === NONE_LANGUAGE_VALUE ? option.value === PLAIN_TEXT_LANGUAGE_VALUE : option.value === language || option.alias.includes(language);
87
86
  }) : undefined;
@@ -92,13 +91,13 @@ export var getToolbarConfig = function getToolbarConfig() {
92
91
  if (!view) {
93
92
  return null;
94
93
  }
95
- return /*#__PURE__*/React.createElement(LanguagePicker, {
94
+ return /*#__PURE__*/React.createElement(CodeBlockLanguagePicker, {
96
95
  api: api,
97
96
  defaultValue: defaultPickerValue,
98
97
  editorView: view,
99
98
  filterOption: languageListFilter,
100
99
  formatMessage: formatMessage,
101
- options: groupedOptions
100
+ languagePickerOptions: languagePickerOptions
102
101
  });
103
102
  }
104
103
  };
@@ -0,0 +1,36 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import React, { useCallback, useState } from 'react';
3
+ import { LanguagePicker } from './LanguagePicker';
4
+ import { getRecentLanguages, saveRecentLanguage } from './recent-languages';
5
+ export var CodeBlockLanguagePicker = function CodeBlockLanguagePicker(_ref) {
6
+ var api = _ref.api,
7
+ defaultValue = _ref.defaultValue,
8
+ editorView = _ref.editorView,
9
+ filterOption = _ref.filterOption,
10
+ formatMessage = _ref.formatMessage,
11
+ languagePickerOptions = _ref.languagePickerOptions;
12
+ var _useState = useState(function () {
13
+ return getRecentLanguages();
14
+ }),
15
+ _useState2 = _slicedToArray(_useState, 2),
16
+ recentLanguageValues = _useState2[0],
17
+ setRecentLanguageValues = _useState2[1];
18
+ var refreshRecentLanguages = useCallback(function () {
19
+ setRecentLanguageValues(getRecentLanguages());
20
+ }, []);
21
+ var handleLanguageSelect = useCallback(function (language) {
22
+ saveRecentLanguage(language);
23
+ setRecentLanguageValues(getRecentLanguages());
24
+ }, []);
25
+ return /*#__PURE__*/React.createElement(LanguagePicker, {
26
+ api: api,
27
+ defaultValue: defaultValue,
28
+ editorView: editorView,
29
+ filterOption: filterOption,
30
+ formatMessage: formatMessage,
31
+ languagePickerOptions: languagePickerOptions,
32
+ recentLanguageValues: recentLanguageValues,
33
+ onLanguageSelect: handleLanguageSelect,
34
+ onMenuOpen: refreshRecentLanguages
35
+ });
36
+ };
@@ -2,7 +2,10 @@
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import "./LanguagePicker.compiled.css";
4
4
  import { ax, ix } from "@compiled/react/runtime";
5
- import React, { Fragment, useCallback, useMemo, useState } from 'react';
5
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
6
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
7
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
8
+ import React, { Fragment, useCallback, useMemo, useRef, useState } from 'react';
6
9
  import Button from '@atlaskit/button/new';
7
10
  import { codeBlockButtonMessages } from '@atlaskit/editor-common/messages';
8
11
  import { akEditorLineHeight } from '@atlaskit/editor-shared-styles';
@@ -10,6 +13,7 @@ import ChevronDownIcon from '@atlaskit/icon/core/chevron-down';
10
13
  import { Box } from '@atlaskit/primitives/compiled';
11
14
  import { PopupSelect, components } from '@atlaskit/select';
12
15
  import { changeLanguage } from '../editor-commands';
16
+ import { createGroupedLanguageOptions } from './language-picker-options';
13
17
  var pickerOptionStyles = null;
14
18
  var styles = {
15
19
  divider: "_h7alglyw _179rglyw _mqm2ia51 _1bsb1osq",
@@ -48,6 +52,25 @@ var menuPopperProps = {
48
52
  enabled: false
49
53
  }]
50
54
  };
55
+ var getRecentlyUsedLanguages = function getRecentlyUsedLanguages(recentLanguageValues, optionsByValue) {
56
+ var recentlyUsedLanguages = [];
57
+ var _iterator = _createForOfIteratorHelper(recentLanguageValues),
58
+ _step;
59
+ try {
60
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
61
+ var recentLanguageValue = _step.value;
62
+ var option = optionsByValue.get(recentLanguageValue);
63
+ if (option) {
64
+ recentlyUsedLanguages.push(option);
65
+ }
66
+ }
67
+ } catch (err) {
68
+ _iterator.e(err);
69
+ } finally {
70
+ _iterator.f();
71
+ }
72
+ return recentlyUsedLanguages;
73
+ };
51
74
  export var LanguagePicker = function LanguagePicker(_ref) {
52
75
  var _api$analytics, _defaultValue$label;
53
76
  var api = _ref.api,
@@ -55,28 +78,58 @@ export var LanguagePicker = function LanguagePicker(_ref) {
55
78
  editorView = _ref.editorView,
56
79
  filterOption = _ref.filterOption,
57
80
  formatMessage = _ref.formatMessage,
58
- options = _ref.options;
81
+ languagePickerOptions = _ref.languagePickerOptions,
82
+ _ref$recentLanguageVa = _ref.recentLanguageValues,
83
+ recentLanguageValues = _ref$recentLanguageVa === void 0 ? [] : _ref$recentLanguageVa,
84
+ onLanguageSelect = _ref.onLanguageSelect,
85
+ onMenuOpen = _ref.onMenuOpen;
59
86
  var editorAnalyticsAPI = api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions;
60
87
  var label = (_defaultValue$label = defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.label) !== null && _defaultValue$label !== void 0 ? _defaultValue$label : formatMessage(codeBlockButtonMessages.selectLanguage);
61
88
  var selectLanguageLabel = formatMessage(codeBlockButtonMessages.selectLanguage);
62
- var _useState = useState(''),
89
+ var _useState = useState(false),
63
90
  _useState2 = _slicedToArray(_useState, 2),
64
- inputValue = _useState2[0],
65
- setInputValue = _useState2[1];
91
+ hasSearchQuery = _useState2[0],
92
+ setHasSearchQuery = _useState2[1];
93
+ var inputValueRef = useRef('');
94
+ var optionsByValue = useMemo(function () {
95
+ return new Map(languagePickerOptions.map(function (option) {
96
+ return [option.value, option];
97
+ }));
98
+ }, [languagePickerOptions]);
99
+ var recentlyUsedLanguages = useMemo(function () {
100
+ return getRecentlyUsedLanguages(recentLanguageValues, optionsByValue);
101
+ }, [recentLanguageValues, optionsByValue]);
102
+ var options = useMemo(function () {
103
+ return createGroupedLanguageOptions({
104
+ formatMessage: formatMessage,
105
+ languages: languagePickerOptions,
106
+ recentlyUsedLanguages: recentlyUsedLanguages
107
+ });
108
+ }, [formatMessage, languagePickerOptions, recentlyUsedLanguages]);
66
109
  var searchOptions = useMemo(function () {
67
110
  return options.flatMap(function (group) {
68
111
  return group.options;
69
112
  });
70
113
  }, [options]);
71
- var hasSearchQuery = inputValue.trim().length > 0;
72
114
  var handleChange = useCallback(function (option) {
115
+ var _option$selectionSour;
73
116
  if (!option) {
74
117
  return;
75
118
  }
76
- changeLanguage(editorAnalyticsAPI)(option.value)(editorView.state, editorView.dispatch);
77
- }, [editorAnalyticsAPI, editorView]);
78
- var handleInputChange = useCallback(function (newInputValue) {
79
- setInputValue(newInputValue);
119
+ var isSearchSelection = inputValueRef.current.trim().length > 0;
120
+ var selectionSource = isSearchSelection ? 'search' : (_option$selectionSour = option.selectionSource) !== null && _option$selectionSour !== void 0 ? _option$selectionSour : 'all';
121
+ var commandSucceeded = changeLanguage(editorAnalyticsAPI)(option.value, selectionSource)(editorView.state, editorView.dispatch);
122
+ if (commandSucceeded) {
123
+ onLanguageSelect === null || onLanguageSelect === void 0 || onLanguageSelect(option.value);
124
+ }
125
+ }, [editorAnalyticsAPI, editorView, onLanguageSelect]);
126
+ var handleInputChange = useCallback(function (newInputValue, actionMeta) {
127
+ // React-select clears the input as part of selecting a value before onChange fires.
128
+ // Keep the last user-typed query so handleChange can report search selections correctly.
129
+ if (!actionMeta || actionMeta.action === 'input-change') {
130
+ inputValueRef.current = newInputValue;
131
+ }
132
+ setHasSearchQuery(newInputValue.trim().length > 0);
80
133
  return newInputValue;
81
134
  }, []);
82
135
  var renderTarget = useCallback(function (_ref2) {
@@ -101,13 +154,13 @@ export var LanguagePicker = function LanguagePicker(_ref) {
101
154
  return /*#__PURE__*/React.createElement(PopupSelect, {
102
155
  components: popupSelectComponents,
103
156
  filterOption: filterOption,
104
- inputValue: inputValue,
105
157
  label: selectLanguageLabel,
106
158
  maxMenuHeight: 300,
107
159
  minMenuWidth: 200,
108
160
  menuPlacement: "auto",
109
161
  onChange: handleChange,
110
162
  onInputChange: handleInputChange,
163
+ onMenuOpen: onMenuOpen,
111
164
  options: hasSearchQuery ? searchOptions : options,
112
165
  popperProps: menuPopperProps,
113
166
  searchThreshold: -1,
@@ -1,4 +1,7 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
5
  import { codeBlockButtonMessages } from '@atlaskit/editor-common/messages';
3
6
  export var NONE_LANGUAGE_VALUE = 'none';
4
7
  export var DETECT_LANGUAGE_VALUE = 'autodetect';
@@ -7,6 +10,7 @@ export var getDetectLanguageOption = function getDetectLanguageOption(formatMess
7
10
  return {
8
11
  alias: [DETECT_LANGUAGE_VALUE],
9
12
  label: formatMessage(codeBlockButtonMessages.detectLanguage),
13
+ selectionSource: 'pinned',
10
14
  value: DETECT_LANGUAGE_VALUE
11
15
  };
12
16
  };
@@ -15,24 +19,37 @@ export var createGroupedLanguageOptions = function createGroupedLanguageOptions(
15
19
  languages = _ref.languages,
16
20
  _ref$recentlyUsedLang = _ref.recentlyUsedLanguages,
17
21
  recentlyUsedLanguages = _ref$recentlyUsedLang === void 0 ? [] : _ref$recentlyUsedLang;
22
+ var recentlyUsedLanguageValues = new Set(recentlyUsedLanguages.map(function (language) {
23
+ return language.value;
24
+ }));
18
25
  var allLanguages = languages.filter(function (language) {
19
- return language.value !== NONE_LANGUAGE_VALUE && language.value !== PLAIN_TEXT_LANGUAGE_VALUE;
26
+ return language.value !== NONE_LANGUAGE_VALUE && language.value !== PLAIN_TEXT_LANGUAGE_VALUE && !recentlyUsedLanguageValues.has(language.value);
20
27
  });
21
28
  var plainTextOption = languages.find(function (language) {
22
29
  return language.value === PLAIN_TEXT_LANGUAGE_VALUE;
23
30
  });
24
31
  var pinnedOptions = [getDetectLanguageOption(formatMessage)];
25
32
  if (plainTextOption) {
26
- pinnedOptions.push(plainTextOption);
33
+ pinnedOptions.push(_objectSpread(_objectSpread({}, plainTextOption), {}, {
34
+ selectionSource: 'pinned'
35
+ }));
27
36
  }
28
37
  return [{
29
38
  label: '',
30
39
  options: pinnedOptions
31
40
  }].concat(_toConsumableArray(recentlyUsedLanguages.length > 0 ? [{
32
41
  label: formatMessage(codeBlockButtonMessages.recentlyUsed),
33
- options: recentlyUsedLanguages
42
+ options: recentlyUsedLanguages.map(function (language) {
43
+ return _objectSpread(_objectSpread({}, language), {}, {
44
+ selectionSource: 'recentlyUsed'
45
+ });
46
+ })
34
47
  }] : []), [{
35
48
  label: formatMessage(codeBlockButtonMessages.all),
36
- options: allLanguages
49
+ options: allLanguages.map(function (language) {
50
+ return _objectSpread(_objectSpread({}, language), {}, {
51
+ selectionSource: 'all'
52
+ });
53
+ })
37
54
  }]);
38
55
  };
@@ -0,0 +1,43 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { StorageClient } from '@atlaskit/frontend-utilities/storage-client';
3
+ import { DEFAULT_LANGUAGES, getLanguageIdentifier } from '../pm-plugins/language-list';
4
+ import { DETECT_LANGUAGE_VALUE, NONE_LANGUAGE_VALUE, PLAIN_TEXT_LANGUAGE_VALUE } from './language-picker-options';
5
+ export var RECENT_LANGUAGES_STORAGE_KEY = 'recently-used-languages';
6
+ var RECENT_LANGUAGES_STORAGE_CLIENT_KEY = '@atlaskit/editor-plugin-code-block';
7
+ var MAX_RECENT_LANGUAGES = 3;
8
+ var RECENT_LANGUAGE_BLOCKLIST = new Set([DETECT_LANGUAGE_VALUE, NONE_LANGUAGE_VALUE, PLAIN_TEXT_LANGUAGE_VALUE]);
9
+ var KNOWN_LANGUAGE_VALUES = new Set(DEFAULT_LANGUAGES.map(function (language) {
10
+ return getLanguageIdentifier(language);
11
+ }));
12
+ var recentLanguagesStorageClient = new StorageClient(RECENT_LANGUAGES_STORAGE_CLIENT_KEY);
13
+ var isValidRecentLanguage = function isValidRecentLanguage(language) {
14
+ return KNOWN_LANGUAGE_VALUES.has(language) && !RECENT_LANGUAGE_BLOCKLIST.has(language);
15
+ };
16
+ var readRecentLanguages = function readRecentLanguages() {
17
+ var storedValue = recentLanguagesStorageClient.getItem(RECENT_LANGUAGES_STORAGE_KEY);
18
+ return Array.isArray(storedValue) ? storedValue : [];
19
+ };
20
+ export var getRecentLanguages = function getRecentLanguages() {
21
+ try {
22
+ return readRecentLanguages();
23
+ } catch (_unused) {
24
+ return [];
25
+ }
26
+ };
27
+ export var saveRecentLanguage = function saveRecentLanguage(language) {
28
+ if (!isValidRecentLanguage(language)) {
29
+ return;
30
+ }
31
+ try {
32
+ var recentLanguages = readRecentLanguages();
33
+ var nextRecentLanguages = Array.from(new Set([language].concat(_toConsumableArray(recentLanguages)))).slice(0, MAX_RECENT_LANGUAGES);
34
+
35
+ // StorageClient only exposes setItemWithExpiry; omitting the duration stores without expiry.
36
+ recentLanguagesStorageClient.setItemWithExpiry(RECENT_LANGUAGES_STORAGE_KEY, nextRecentLanguages);
37
+ } catch (_unused2) {
38
+ return;
39
+ }
40
+ };
41
+ export var clearRecentLanguages = function clearRecentLanguages() {
42
+ recentLanguagesStorageClient.removeItem(RECENT_LANGUAGES_STORAGE_KEY);
43
+ };
@@ -2,9 +2,10 @@ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
3
  import type { Command, EditorCommand } from '@atlaskit/editor-common/types';
4
4
  import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
5
+ import type { LanguagePickerSelectionSource } from '../ui/language-picker-options';
5
6
  export declare const removeCodeBlockWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => Command;
6
7
  export declare const removeCodeBlock: Command;
7
- export declare const changeLanguage: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (language: string | null) => Command;
8
+ export declare const changeLanguage: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (language: string | null, selectionSource?: LanguagePickerSelectionSource) => Command;
8
9
  export declare const copyContentToClipboardWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => Command;
9
10
  export declare const copyContentToClipboard: Command;
10
11
  export declare const resetCopiedState: Command;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { LanguagePickerProps } from './LanguagePicker';
3
+ type CodeBlockLanguagePickerProps = Omit<LanguagePickerProps, 'recentLanguageValues' | 'onLanguageSelect' | 'onMenuOpen'>;
4
+ export declare const CodeBlockLanguagePicker: ({ api, defaultValue, editorView, filterOption, formatMessage, languagePickerOptions, }: CodeBlockLanguagePickerProps) => React.JSX.Element;
5
+ export {};
@@ -7,14 +7,16 @@ import type { IntlShape } from 'react-intl';
7
7
  import type { ExtractInjectionAPI, SelectOption } from '@atlaskit/editor-common/types';
8
8
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
9
9
  import type { CodeBlockPlugin } from '../index';
10
- import type { LanguagePickerOption, LanguagePickerOptionGroup } from './language-picker-options';
11
- type LanguagePickerProps = {
10
+ import type { LanguagePickerOption } from './language-picker-options';
11
+ export type LanguagePickerProps = {
12
12
  api: ExtractInjectionAPI<CodeBlockPlugin> | undefined;
13
13
  defaultValue?: LanguagePickerOption;
14
14
  editorView: EditorView;
15
15
  filterOption: (option: SelectOption<LanguagePickerOption>, rawInput: string) => boolean;
16
16
  formatMessage: IntlShape['formatMessage'];
17
- options: LanguagePickerOptionGroup[];
17
+ languagePickerOptions: LanguagePickerOption[];
18
+ onLanguageSelect?: (language: string) => void;
19
+ onMenuOpen?: () => void;
20
+ recentLanguageValues?: string[];
18
21
  };
19
- export declare const LanguagePicker: ({ api, defaultValue, editorView, filterOption, formatMessage, options, }: LanguagePickerProps) => React.JSX.Element;
20
- export {};
22
+ export declare const LanguagePicker: ({ api, defaultValue, editorView, filterOption, formatMessage, languagePickerOptions, recentLanguageValues, onLanguageSelect, onMenuOpen, }: LanguagePickerProps) => React.JSX.Element;
@@ -3,9 +3,11 @@ import type { GroupType } from '@atlaskit/select';
3
3
  export declare const NONE_LANGUAGE_VALUE = "none";
4
4
  export declare const DETECT_LANGUAGE_VALUE = "autodetect";
5
5
  export declare const PLAIN_TEXT_LANGUAGE_VALUE = "text";
6
+ export type LanguagePickerSelectionSource = 'all' | 'pinned' | 'recentlyUsed' | 'search';
6
7
  export type LanguagePickerOption = {
7
8
  alias: readonly string[];
8
9
  label: string;
10
+ selectionSource?: LanguagePickerSelectionSource;
9
11
  value: string;
10
12
  };
11
13
  export type LanguagePickerOptionGroup = GroupType<LanguagePickerOption>;
@@ -0,0 +1,4 @@
1
+ export declare const RECENT_LANGUAGES_STORAGE_KEY = "recently-used-languages";
2
+ export declare const getRecentLanguages: () => string[];
3
+ export declare const saveRecentLanguage: (language: string) => void;
4
+ export declare const clearRecentLanguages: () => void;
@@ -2,9 +2,10 @@ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
2
2
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
3
3
  import type { Command, EditorCommand } from '@atlaskit/editor-common/types';
4
4
  import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
5
+ import type { LanguagePickerSelectionSource } from '../ui/language-picker-options';
5
6
  export declare const removeCodeBlockWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => Command;
6
7
  export declare const removeCodeBlock: Command;
7
- export declare const changeLanguage: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (language: string | null) => Command;
8
+ export declare const changeLanguage: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (language: string | null, selectionSource?: LanguagePickerSelectionSource) => Command;
8
9
  export declare const copyContentToClipboardWithAnalytics: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => Command;
9
10
  export declare const copyContentToClipboard: Command;
10
11
  export declare const resetCopiedState: Command;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { LanguagePickerProps } from './LanguagePicker';
3
+ type CodeBlockLanguagePickerProps = Omit<LanguagePickerProps, 'recentLanguageValues' | 'onLanguageSelect' | 'onMenuOpen'>;
4
+ export declare const CodeBlockLanguagePicker: ({ api, defaultValue, editorView, filterOption, formatMessage, languagePickerOptions, }: CodeBlockLanguagePickerProps) => React.JSX.Element;
5
+ export {};
@@ -7,14 +7,16 @@ import type { IntlShape } from 'react-intl';
7
7
  import type { ExtractInjectionAPI, SelectOption } from '@atlaskit/editor-common/types';
8
8
  import type { EditorView } from '@atlaskit/editor-prosemirror/view';
9
9
  import type { CodeBlockPlugin } from '../index';
10
- import type { LanguagePickerOption, LanguagePickerOptionGroup } from './language-picker-options';
11
- type LanguagePickerProps = {
10
+ import type { LanguagePickerOption } from './language-picker-options';
11
+ export type LanguagePickerProps = {
12
12
  api: ExtractInjectionAPI<CodeBlockPlugin> | undefined;
13
13
  defaultValue?: LanguagePickerOption;
14
14
  editorView: EditorView;
15
15
  filterOption: (option: SelectOption<LanguagePickerOption>, rawInput: string) => boolean;
16
16
  formatMessage: IntlShape['formatMessage'];
17
- options: LanguagePickerOptionGroup[];
17
+ languagePickerOptions: LanguagePickerOption[];
18
+ onLanguageSelect?: (language: string) => void;
19
+ onMenuOpen?: () => void;
20
+ recentLanguageValues?: string[];
18
21
  };
19
- export declare const LanguagePicker: ({ api, defaultValue, editorView, filterOption, formatMessage, options, }: LanguagePickerProps) => React.JSX.Element;
20
- export {};
22
+ export declare const LanguagePicker: ({ api, defaultValue, editorView, filterOption, formatMessage, languagePickerOptions, recentLanguageValues, onLanguageSelect, onMenuOpen, }: LanguagePickerProps) => React.JSX.Element;
@@ -3,9 +3,11 @@ import type { GroupType } from '@atlaskit/select';
3
3
  export declare const NONE_LANGUAGE_VALUE = "none";
4
4
  export declare const DETECT_LANGUAGE_VALUE = "autodetect";
5
5
  export declare const PLAIN_TEXT_LANGUAGE_VALUE = "text";
6
+ export type LanguagePickerSelectionSource = 'all' | 'pinned' | 'recentlyUsed' | 'search';
6
7
  export type LanguagePickerOption = {
7
8
  alias: readonly string[];
8
9
  label: string;
10
+ selectionSource?: LanguagePickerSelectionSource;
9
11
  value: string;
10
12
  };
11
13
  export type LanguagePickerOptionGroup = GroupType<LanguagePickerOption>;
@@ -0,0 +1,4 @@
1
+ export declare const RECENT_LANGUAGES_STORAGE_KEY = "recently-used-languages";
2
+ export declare const getRecentLanguages: () => string[];
3
+ export declare const saveRecentLanguage: (language: string) => void;
4
+ export declare const clearRecentLanguages: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block",
3
- "version": "12.1.5",
3
+ "version": "12.1.7",
4
4
  "description": "Code block plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -27,7 +27,7 @@
27
27
  "sideEffects": false,
28
28
  "atlaskit:src": "src/index.ts",
29
29
  "dependencies": {
30
- "@atlaskit/adf-schema": "^52.13.0",
30
+ "@atlaskit/adf-schema": "^52.14.0",
31
31
  "@atlaskit/button": "^23.11.0",
32
32
  "@atlaskit/code": "^17.5.0",
33
33
  "@atlaskit/css": "^0.19.0",
@@ -43,18 +43,19 @@
43
43
  "@atlaskit/editor-prosemirror": "^7.3.0",
44
44
  "@atlaskit/editor-shared-styles": "^3.11.0",
45
45
  "@atlaskit/editor-toolbar": "^1.7.0",
46
- "@atlaskit/icon": "^35.0.0",
46
+ "@atlaskit/frontend-utilities": "^3.3.0",
47
+ "@atlaskit/icon": "^35.1.0",
47
48
  "@atlaskit/platform-feature-flags": "^1.1.0",
48
49
  "@atlaskit/primitives": "^19.0.0",
49
50
  "@atlaskit/prosemirror-input-rules": "^3.7.0",
50
51
  "@atlaskit/select": "^21.12.0",
51
- "@atlaskit/tmp-editor-statsig": "^82.0.0",
52
+ "@atlaskit/tmp-editor-statsig": "^83.0.0",
52
53
  "@atlaskit/tokens": "^13.0.0",
53
54
  "@babel/runtime": "^7.0.0",
54
55
  "@compiled/react": "^0.20.0"
55
56
  },
56
57
  "peerDependencies": {
57
- "@atlaskit/editor-common": "^114.38.0",
58
+ "@atlaskit/editor-common": "^114.47.0",
58
59
  "react": "^18.2.0",
59
60
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
60
61
  },
@@ -111,6 +112,7 @@
111
112
  }
112
113
  },
113
114
  "devDependencies": {
115
+ "react": "^18.2.0",
114
116
  "react-intl": "^6.6.2"
115
117
  }
116
118
  }