@sveltia/ui 0.40.5 → 0.41.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.
@@ -56,7 +56,12 @@
56
56
  const backticks = '```';
57
57
  const editorStore = createEditorStore();
58
58
 
59
- editorStore.config = { ...editorStore.config, isCodeEditor: true, defaultLanguage: lang };
59
+ editorStore.config = {
60
+ ...editorStore.config,
61
+ useMarkdownShortcuts: false,
62
+ isCodeEditor: true,
63
+ defaultLanguage: lang,
64
+ };
60
65
 
61
66
  setContext('editorStore', editorStore);
62
67
 
@@ -1,9 +1,12 @@
1
- export function initEditor({ components, isCodeEditor, defaultLanguage, }: TextEditorConfig): {
1
+ export function getSelectionTypes(): TextEditorSelectionState;
2
+ export function onEditorUpdate(editor: LexicalEditor): void;
3
+ export function initEditor({ components, useMarkdownShortcuts, isCodeEditor, defaultLanguage, }: TextEditorConfig): {
2
4
  editor: LexicalEditor;
3
5
  dispose: () => void;
4
6
  };
5
7
  export function loadCodeHighlighter(lang: string): Promise<void>;
6
8
  export function convertMarkdownToLexical(editor: LexicalEditor, value: string): Promise<void>;
7
9
  export function focusEditor(editor: LexicalEditor): Promise<void>;
8
- import type { TextEditorConfig } from '../../typedefs';
10
+ import type { TextEditorSelectionState } from '../../typedefs';
9
11
  import type { LexicalEditor } from 'lexical';
12
+ import type { TextEditorConfig } from '../../typedefs';
@@ -32,6 +32,7 @@ import {
32
32
  import {
33
33
  $convertFromMarkdownString as convertFromMarkdownString,
34
34
  $convertToMarkdownString as convertToMarkdownString,
35
+ registerMarkdownShortcuts,
35
36
  TRANSFORMERS,
36
37
  } from '@lexical/markdown';
37
38
  import {
@@ -146,9 +147,10 @@ const editorConfig = {
146
147
 
147
148
  /**
148
149
  * Get the current selection’s block node key as well as block and inline level types.
150
+ * @internal
149
151
  * @returns {TextEditorSelectionState} Current selection state.
150
152
  */
151
- const getSelectionTypes = () => {
153
+ export const getSelectionTypes = () => {
152
154
  const selection = getSelection();
153
155
 
154
156
  if (!isRangeSelection(selection)) {
@@ -219,9 +221,10 @@ const getSelectionTypes = () => {
219
221
 
220
222
  /**
221
223
  * Listen to changes made on the editor and trigger the Update event.
224
+ * @internal
222
225
  * @param {LexicalEditor} editor Editor instance.
223
226
  */
224
- const onEditorUpdate = (editor) => {
227
+ export const onEditorUpdate = (editor) => {
225
228
  editor.getRootElement()?.dispatchEvent(
226
229
  new CustomEvent('Update', {
227
230
  detail: {
@@ -250,6 +253,7 @@ const onEditorUpdate = (editor) => {
250
253
  */
251
254
  export const initEditor = ({
252
255
  components = [],
256
+ useMarkdownShortcuts,
253
257
  isCodeEditor = false,
254
258
  defaultLanguage = 'plain',
255
259
  }) => {
@@ -267,6 +271,7 @@ export const initEditor = ({
267
271
  * @param {(() => void) | undefined | null} unregister Cleanup handler.
268
272
  */
269
273
  const addUnregister = (unregister) => {
274
+ /* v8 ignore next */
270
275
  if (typeof unregister === 'function') {
271
276
  unregisters.push(unregister);
272
277
  }
@@ -276,6 +281,10 @@ export const initEditor = ({
276
281
  addUnregister(registerDragonSupport(editor));
277
282
  addUnregister(registerHistory(editor, createEmptyHistoryState(), 1000));
278
283
 
284
+ if (useMarkdownShortcuts) {
285
+ addUnregister(registerMarkdownShortcuts(editor, allTransformers));
286
+ }
287
+
279
288
  addUnregister(
280
289
  registerCodeHighlighting(editor, {
281
290
  defaultLanguage,
@@ -342,10 +351,12 @@ export const initEditor = ({
342
351
 
343
352
  editor.update(() => {
344
353
  // Prevent CodeNode from being removed
354
+ /* v8 ignore next */
345
355
  if (isCodeEditor) {
346
356
  const root = getRoot();
347
357
  const children = root.getChildren();
348
358
 
359
+ // c8 ignore next 3
349
360
  if (children.length === 1 && !isCodeNode(children[0])) {
350
361
  children[0].remove();
351
362
  }
@@ -434,7 +445,8 @@ export const loadCodeHighlighter = async (lang) => {
434
445
  const canonicalLang = Object.entries(prismComponents.languages).find(
435
446
  // @ts-ignore
436
447
  ([key, { alias }]) =>
437
- key === lang || (Array.isArray(alias) ? alias.includes(lang) : alias === lang),
448
+ key === lang ||
449
+ (Array.isArray(alias) ? alias.includes(lang) : /* v8 ignore next */ alias === lang),
438
450
  )?.[0];
439
451
 
440
452
  if (!canonicalLang) {
@@ -17,8 +17,16 @@ export const createEditorStore = () => {
17
17
  let initialized = $state(false);
18
18
  /** @type {LexicalEditor | undefined} */
19
19
  let editor = $state();
20
+
20
21
  /** @type {TextEditorConfig} */
21
- let config = $state({ modes: [], enabledButtons: [], components: [], isCodeEditor: false });
22
+ let config = $state({
23
+ modes: [],
24
+ enabledButtons: [],
25
+ components: [],
26
+ useMarkdownShortcuts: true,
27
+ isCodeEditor: false,
28
+ });
29
+
22
30
  /** @type {string} */
23
31
  let inputValue = $state('');
24
32
  /** @type {TextEditorSelectionState} */
@@ -31,6 +31,8 @@
31
31
  * @property {TextEditorMode[]} [modes] Enabled modes.
32
32
  * @property {(TextEditorBlockType | TextEditorInlineType)[]} [buttons] Enabled buttons.
33
33
  * @property {TextEditorComponent[]} [components] Editor components.
34
+ * @property {boolean} [useMarkdownShortcuts] Whether to enable Markdown keyboard shortcuts in the
35
+ * rich text editor.
34
36
  * @property {string} [class] The `class` attribute on the wrapper element.
35
37
  * @property {boolean} [hidden] Whether to hide the widget.
36
38
  * @property {boolean} [disabled] Whether to disable the widget. An alias of the `aria-disabled`
@@ -55,6 +57,7 @@
55
57
  modes = ['rich-text', 'plain-text'],
56
58
  buttons = [...INLINE_BUTTON_TYPES, ...BLOCK_BUTTON_TYPES],
57
59
  components = [],
60
+ useMarkdownShortcuts = true,
58
61
  hidden = false,
59
62
  disabled = false,
60
63
  readonly = false,
@@ -68,7 +71,13 @@
68
71
  const editorStore = createEditorStore();
69
72
 
70
73
  // svelte-ignore state_referenced_locally
71
- editorStore.config = { ...editorStore.config, modes, enabledButtons: buttons, components };
74
+ editorStore.config = {
75
+ ...editorStore.config,
76
+ modes,
77
+ enabledButtons: buttons,
78
+ components,
79
+ useMarkdownShortcuts,
80
+ };
72
81
 
73
82
  setContext('editorStore', editorStore);
74
83
 
@@ -29,6 +29,11 @@ declare const TextEditor: import("svelte").Component<{
29
29
  * Editor components.
30
30
  */
31
31
  components?: TextEditorComponent[] | undefined;
32
+ /**
33
+ * Whether to enable Markdown keyboard shortcuts in the
34
+ * rich text editor.
35
+ */
36
+ useMarkdownShortcuts?: boolean | undefined;
32
37
  /**
33
38
  * The `class` attribute on the wrapper element.
34
39
  */
@@ -87,6 +92,11 @@ type Props = {
87
92
  * Editor components.
88
93
  */
89
94
  components?: TextEditorComponent[] | undefined;
95
+ /**
96
+ * Whether to enable Markdown keyboard shortcuts in the
97
+ * rich text editor.
98
+ */
99
+ useMarkdownShortcuts?: boolean | undefined;
90
100
  /**
91
101
  * The `class` attribute on the wrapper element.
92
102
  */
@@ -1,5 +1,10 @@
1
+ export function getTableColumnsSize(table: TableNode): number;
2
+ export function createTableCell(textContent: string): TableCellNode;
3
+ export function mapToTableCells(textContent: string): TableCellNode[] | null;
1
4
  /**
2
5
  * @type {ElementTransformer}
3
6
  */
4
7
  export const TABLE: ElementTransformer;
8
+ import { TableNode } from '@lexical/table';
9
+ import { TableCellNode } from '@lexical/table';
5
10
  import type { ElementTransformer } from '@lexical/markdown';
@@ -32,21 +32,23 @@ const TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/;
32
32
 
33
33
  /**
34
34
  * Returns the number of columns in the table.
35
+ * @internal
35
36
  * @param {TableNode} table
36
37
  * @returns {number}
37
38
  */
38
- function getTableColumnsSize(table) {
39
+ export const getTableColumnsSize = (table) => {
39
40
  const row = table.getFirstChild();
40
41
 
41
42
  return isTableRowNode(row) ? row.getChildrenSize() : 0;
42
- }
43
+ };
43
44
 
44
45
  /**
45
46
  * Creates a table cell with the given text content.
47
+ * @internal
46
48
  * @param {string} textContent
47
49
  * @returns {TableCellNode}
48
50
  */
49
- const createTableCell = (textContent) => {
51
+ export const createTableCell = (textContent) => {
50
52
  textContent = textContent.replace(/\\n/g, '\n');
51
53
 
52
54
  const cell = createTableCellNode(TableCellHeaderStates.NO_STATUS);
@@ -58,10 +60,11 @@ const createTableCell = (textContent) => {
58
60
 
59
61
  /**
60
62
  * Maps the given text content to an array of table cells.
63
+ * @internal
61
64
  * @param {string} textContent
62
65
  * @returns {TableCellNode[] | null}
63
66
  */
64
- const mapToTableCells = (textContent) => {
67
+ export const mapToTableCells = (textContent) => {
65
68
  const [, match] = textContent.match(TABLE_ROW_REG_EXP) ?? [];
66
69
 
67
70
  if (!match) {
@@ -74,8 +74,7 @@
74
74
  aria-readonly={readonly}
75
75
  aria-required={required}
76
76
  aria-invalid={invalid}
77
- class:auto-resize={autoResize}
78
- ></textarea>
77
+ class:auto-resize={autoResize}></textarea>
79
78
  {#if autoResize}
80
79
  <div class="clone" aria-hidden="true" {dir}>{value}</div>
81
80
  {/if}
@@ -556,6 +556,7 @@ export const activateGroup = (paramsOrGetter) => (parent) => {
556
556
  const initialParams = isGetter ? paramsOrGetter() : paramsOrGetter;
557
557
  const group = new Group(/** @type {HTMLElement} */ (parent), initialParams);
558
558
 
559
+ /* v8 ignore next 4 */
559
560
  if (isGetter) {
560
561
  $effect(() => {
561
562
  group.onUpdate(paramsOrGetter());
@@ -706,6 +706,11 @@ export type TextEditorConfig = {
706
706
  * Editor components.
707
707
  */
708
708
  components: TextEditorComponent[];
709
+ /**
710
+ * Whether to enable Markdown keyboard shortcuts in the
711
+ * rich text editor.
712
+ */
713
+ useMarkdownShortcuts: boolean;
709
714
  /**
710
715
  * Whether the editor is used as a code editor.
711
716
  */
package/dist/typedefs.js CHANGED
@@ -291,6 +291,8 @@
291
291
  * @property {(TextEditorBlockType | TextEditorInlineType)[]} enabledButtons Enabled buttons for the
292
292
  * editor.
293
293
  * @property {TextEditorComponent[]} components Editor components.
294
+ * @property {boolean} useMarkdownShortcuts Whether to enable Markdown keyboard shortcuts in the
295
+ * rich text editor.
294
296
  * @property {boolean} isCodeEditor Whether the editor is used as a code editor.
295
297
  * @property {string} [defaultLanguage] Default language for the code editor.
296
298
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltia/ui",
3
- "version": "0.40.5",
3
+ "version": "0.41.0",
4
4
  "description": "A collection of Svelte components and utilities for building user interfaces.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,55 +33,55 @@
33
33
  "!dist/**/*.test.*"
34
34
  ],
35
35
  "dependencies": {
36
- "@lexical/code": "^0.45.0",
37
- "@lexical/code-prism": "^0.45.0",
38
- "@lexical/dragon": "^0.45.0",
39
- "@lexical/extension": "^0.45.0",
40
- "@lexical/history": "^0.45.0",
41
- "@lexical/link": "^0.45.0",
42
- "@lexical/list": "^0.45.0",
43
- "@lexical/markdown": "^0.45.0",
44
- "@lexical/rich-text": "^0.45.0",
45
- "@lexical/selection": "^0.45.0",
46
- "@lexical/table": "^0.45.0",
47
- "@lexical/utils": "^0.45.0",
48
- "@sveltia/i18n": "^1.1.1",
36
+ "@lexical/code": "^0.46.0",
37
+ "@lexical/code-prism": "^0.46.0",
38
+ "@lexical/dragon": "^0.46.0",
39
+ "@lexical/extension": "^0.46.0",
40
+ "@lexical/history": "^0.46.0",
41
+ "@lexical/link": "^0.46.0",
42
+ "@lexical/list": "^0.46.0",
43
+ "@lexical/markdown": "^0.46.0",
44
+ "@lexical/rich-text": "^0.46.0",
45
+ "@lexical/selection": "^0.46.0",
46
+ "@lexical/table": "^0.46.0",
47
+ "@lexical/utils": "^0.46.0",
48
+ "@sveltia/i18n": "^1.1.2",
49
49
  "@sveltia/utils": "^0.10.7",
50
- "lexical": "^0.45.0",
50
+ "lexical": "^0.46.0",
51
51
  "prismjs": "^1.30.0",
52
52
  "yaml": "^2.9.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@sveltejs/adapter-auto": "^7.0.1",
56
- "@sveltejs/kit": "^2.64.0",
56
+ "@sveltejs/kit": "^2.68.0",
57
57
  "@sveltejs/package": "^2.5.8",
58
58
  "@sveltejs/vite-plugin-svelte": "^7.1.2",
59
- "@vitest/coverage-v8": "^4.1.8",
59
+ "@vitest/coverage-v8": "^4.1.9",
60
60
  "cspell": "^10.0.1",
61
61
  "eslint": "^9.39.4",
62
62
  "eslint-config-airbnb-extended": "^3.1.0",
63
63
  "eslint-config-prettier": "^10.1.8",
64
64
  "eslint-plugin-import": "^2.32.0",
65
- "eslint-plugin-jsdoc": "^63.0.2",
66
- "eslint-plugin-package-json": "^1.3.0",
67
- "eslint-plugin-svelte": "^3.19.0",
68
- "globals": "^17.6.0",
69
- "happy-dom": "^20.10.2",
70
- "oxlint": "^1.69.0",
65
+ "eslint-plugin-jsdoc": "^63.0.10",
66
+ "eslint-plugin-package-json": "^1.5.0",
67
+ "eslint-plugin-svelte": "^3.20.0",
68
+ "globals": "^17.7.0",
69
+ "happy-dom": "^20.10.6",
70
+ "oxlint": "^1.71.0",
71
71
  "postcss": "^8.5.15",
72
72
  "postcss-html": "^1.8.1",
73
- "prettier": "^3.8.4",
74
- "prettier-plugin-svelte": "^4.1.0",
75
- "sass": "^1.100.0",
76
- "stylelint": "^17.13.0",
73
+ "prettier": "^3.9.1",
74
+ "prettier-plugin-svelte": "^4.1.1",
75
+ "sass": "^1.101.0",
76
+ "stylelint": "^17.14.0",
77
77
  "stylelint-config-recommended-scss": "^17.0.1",
78
78
  "stylelint-scss": "^7.2.0",
79
- "svelte": "^5.56.3",
80
- "svelte-check": "^4.6.0",
79
+ "svelte": "^5.56.4",
80
+ "svelte-check": "^4.7.1",
81
81
  "svelte-preprocess": "^6.0.5",
82
82
  "tslib": "^2.8.1",
83
- "vite": "^8.0.16",
84
- "vitest": "^4.1.8"
83
+ "vite": "^8.1.0",
84
+ "vitest": "^4.1.9"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "svelte": "^5.0.0"