@semantic-components/editor 0.63.0 → 0.65.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.
Files changed (132) hide show
  1. package/esm2022/index.js +2 -0
  2. package/esm2022/index.js.map +1 -0
  3. package/esm2022/lib/components/editor/editor-align-center-button.js +38 -0
  4. package/esm2022/lib/components/editor/editor-align-center-button.js.map +1 -0
  5. package/esm2022/lib/components/editor/editor-align-justify-button.js +38 -0
  6. package/esm2022/lib/components/editor/editor-align-justify-button.js.map +1 -0
  7. package/esm2022/lib/components/editor/editor-align-left-button.js +37 -0
  8. package/esm2022/lib/components/editor/editor-align-left-button.js.map +1 -0
  9. package/esm2022/lib/components/editor/editor-align-right-button.js +37 -0
  10. package/esm2022/lib/components/editor/editor-align-right-button.js.map +1 -0
  11. package/esm2022/lib/components/editor/editor-blockquote-button.js +37 -0
  12. package/esm2022/lib/components/editor/editor-blockquote-button.js.map +1 -0
  13. package/esm2022/lib/components/editor/editor-bold-button.js +37 -0
  14. package/esm2022/lib/components/editor/editor-bold-button.js.map +1 -0
  15. package/esm2022/lib/components/editor/editor-bullet-list-button.js +37 -0
  16. package/esm2022/lib/components/editor/editor-bullet-list-button.js.map +1 -0
  17. package/esm2022/lib/components/editor/editor-char-count.js +40 -0
  18. package/esm2022/lib/components/editor/editor-char-count.js.map +1 -0
  19. package/esm2022/lib/components/editor/editor-clear-formatting-button.js +36 -0
  20. package/esm2022/lib/components/editor/editor-clear-formatting-button.js.map +1 -0
  21. package/esm2022/lib/components/editor/editor-code-button.js +46 -0
  22. package/esm2022/lib/components/editor/editor-code-button.js.map +1 -0
  23. package/esm2022/lib/components/editor/editor-content.js +78 -0
  24. package/esm2022/lib/components/editor/editor-content.js.map +1 -0
  25. package/esm2022/lib/components/editor/editor-count.js +27 -0
  26. package/esm2022/lib/components/editor/editor-count.js.map +1 -0
  27. package/esm2022/lib/components/editor/editor-footer.js +27 -0
  28. package/esm2022/lib/components/editor/editor-footer.js.map +1 -0
  29. package/esm2022/lib/components/editor/editor-header.js +27 -0
  30. package/esm2022/lib/components/editor/editor-header.js.map +1 -0
  31. package/esm2022/lib/components/editor/editor-heading-select.js +48 -0
  32. package/esm2022/lib/components/editor/editor-heading-select.js.map +1 -0
  33. package/esm2022/lib/components/editor/editor-horizontal-rule-button.js +36 -0
  34. package/esm2022/lib/components/editor/editor-horizontal-rule-button.js.map +1 -0
  35. package/esm2022/lib/components/editor/editor-italic-button.js +37 -0
  36. package/esm2022/lib/components/editor/editor-italic-button.js.map +1 -0
  37. package/esm2022/lib/components/editor/editor-link-button.js +52 -0
  38. package/esm2022/lib/components/editor/editor-link-button.js.map +1 -0
  39. package/esm2022/lib/components/editor/editor-numbered-list-button.js +37 -0
  40. package/esm2022/lib/components/editor/editor-numbered-list-button.js.map +1 -0
  41. package/esm2022/lib/components/editor/editor-redo-button.js +36 -0
  42. package/esm2022/lib/components/editor/editor-redo-button.js.map +1 -0
  43. package/esm2022/lib/components/editor/editor-separator.js +23 -0
  44. package/esm2022/lib/components/editor/editor-separator.js.map +1 -0
  45. package/esm2022/lib/components/editor/editor-strikethrough-button.js +37 -0
  46. package/esm2022/lib/components/editor/editor-strikethrough-button.js.map +1 -0
  47. package/esm2022/lib/components/editor/editor-toolbar-group.js +27 -0
  48. package/esm2022/lib/components/editor/editor-toolbar-group.js.map +1 -0
  49. package/esm2022/lib/components/editor/editor-toolbar.js +29 -0
  50. package/esm2022/lib/components/editor/editor-toolbar.js.map +1 -0
  51. package/esm2022/lib/components/editor/editor-underline-button.js +37 -0
  52. package/esm2022/lib/components/editor/editor-underline-button.js.map +1 -0
  53. package/esm2022/lib/components/editor/editor-undo-button.js +36 -0
  54. package/esm2022/lib/components/editor/editor-undo-button.js.map +1 -0
  55. package/esm2022/lib/components/editor/editor-word-count.js +42 -0
  56. package/esm2022/lib/components/editor/editor-word-count.js.map +1 -0
  57. package/esm2022/lib/components/editor/editor.js +197 -0
  58. package/esm2022/lib/components/editor/editor.js.map +1 -0
  59. package/{src/lib/components/editor/index.ts → esm2022/lib/components/editor/index.js} +1 -8
  60. package/esm2022/lib/components/editor/index.js.map +1 -0
  61. package/esm2022/lib/components/index.js +2 -0
  62. package/esm2022/lib/components/index.js.map +1 -0
  63. package/esm2022/semantic-components-editor.js +5 -0
  64. package/esm2022/semantic-components-editor.js.map +1 -0
  65. package/lib/components/editor/editor-align-center-button.d.ts +9 -0
  66. package/lib/components/editor/editor-align-justify-button.d.ts +9 -0
  67. package/lib/components/editor/editor-align-left-button.d.ts +9 -0
  68. package/lib/components/editor/editor-align-right-button.d.ts +9 -0
  69. package/lib/components/editor/editor-blockquote-button.d.ts +9 -0
  70. package/lib/components/editor/editor-bold-button.d.ts +9 -0
  71. package/lib/components/editor/editor-bullet-list-button.d.ts +9 -0
  72. package/lib/components/editor/editor-char-count.d.ts +10 -0
  73. package/lib/components/editor/editor-clear-formatting-button.d.ts +9 -0
  74. package/lib/components/editor/editor-code-button.d.ts +9 -0
  75. package/lib/components/editor/editor-content.d.ts +18 -0
  76. package/lib/components/editor/editor-count.d.ts +7 -0
  77. package/lib/components/editor/editor-footer.d.ts +7 -0
  78. package/lib/components/editor/editor-header.d.ts +7 -0
  79. package/lib/components/editor/editor-heading-select.d.ts +9 -0
  80. package/lib/components/editor/editor-horizontal-rule-button.d.ts +9 -0
  81. package/lib/components/editor/editor-italic-button.d.ts +9 -0
  82. package/lib/components/editor/editor-link-button.d.ts +9 -0
  83. package/lib/components/editor/editor-numbered-list-button.d.ts +9 -0
  84. package/lib/components/editor/editor-redo-button.d.ts +9 -0
  85. package/lib/components/editor/editor-separator.d.ts +7 -0
  86. package/lib/components/editor/editor-strikethrough-button.d.ts +9 -0
  87. package/lib/components/editor/editor-toolbar-group.d.ts +7 -0
  88. package/lib/components/editor/editor-toolbar.d.ts +7 -0
  89. package/lib/components/editor/editor-underline-button.d.ts +9 -0
  90. package/lib/components/editor/editor-undo-button.d.ts +9 -0
  91. package/lib/components/editor/editor-word-count.d.ts +10 -0
  92. package/lib/components/editor/editor.d.ts +29 -0
  93. package/lib/components/editor/index.d.ts +28 -0
  94. package/package.json +15 -3
  95. package/semantic-components-editor.d.ts +5 -0
  96. package/eslint.config.mjs +0 -48
  97. package/ng-package.json +0 -8
  98. package/project.json +0 -28
  99. package/src/lib/components/editor/README.md +0 -354
  100. package/src/lib/components/editor/editor-align-center-button.ts +0 -45
  101. package/src/lib/components/editor/editor-align-justify-button.ts +0 -45
  102. package/src/lib/components/editor/editor-align-left-button.ts +0 -44
  103. package/src/lib/components/editor/editor-align-right-button.ts +0 -44
  104. package/src/lib/components/editor/editor-blockquote-button.ts +0 -44
  105. package/src/lib/components/editor/editor-bold-button.ts +0 -44
  106. package/src/lib/components/editor/editor-bullet-list-button.ts +0 -44
  107. package/src/lib/components/editor/editor-char-count.ts +0 -42
  108. package/src/lib/components/editor/editor-clear-formatting-button.ts +0 -42
  109. package/src/lib/components/editor/editor-code-button.ts +0 -52
  110. package/src/lib/components/editor/editor-content.ts +0 -107
  111. package/src/lib/components/editor/editor-count.ts +0 -28
  112. package/src/lib/components/editor/editor-footer.ts +0 -30
  113. package/src/lib/components/editor/editor-header.ts +0 -27
  114. package/src/lib/components/editor/editor-heading-select.ts +0 -48
  115. package/src/lib/components/editor/editor-horizontal-rule-button.ts +0 -42
  116. package/src/lib/components/editor/editor-italic-button.ts +0 -44
  117. package/src/lib/components/editor/editor-link-button.ts +0 -58
  118. package/src/lib/components/editor/editor-numbered-list-button.ts +0 -44
  119. package/src/lib/components/editor/editor-redo-button.ts +0 -42
  120. package/src/lib/components/editor/editor-separator.ts +0 -25
  121. package/src/lib/components/editor/editor-strikethrough-button.ts +0 -44
  122. package/src/lib/components/editor/editor-toolbar-group.ts +0 -27
  123. package/src/lib/components/editor/editor-toolbar.ts +0 -32
  124. package/src/lib/components/editor/editor-underline-button.ts +0 -44
  125. package/src/lib/components/editor/editor-undo-button.ts +0 -42
  126. package/src/lib/components/editor/editor-word-count.ts +0 -43
  127. package/src/lib/components/editor/editor.ts +0 -211
  128. package/tsconfig.json +0 -28
  129. package/tsconfig.lib.json +0 -12
  130. package/tsconfig.lib.prod.json +0 -7
  131. /package/{src/index.ts → index.d.ts} +0 -0
  132. /package/{src/lib/components/index.ts → lib/components/index.d.ts} +0 -0
@@ -1,42 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'span[sc-editor-char-count]',
14
- template: `
15
- {{ charCount() }} characters
16
- `,
17
- host: {
18
- 'data-slot': 'editor-char-count',
19
- '[class]': 'class()',
20
- },
21
- encapsulation: ViewEncapsulation.None,
22
- changeDetection: ChangeDetectionStrategy.OnPush,
23
- })
24
- export class ScEditorCharCount {
25
- readonly editor = inject(SC_EDITOR);
26
- readonly classInput = input<string>('', { alias: 'class' });
27
-
28
- protected readonly class = computed(() => cn('', this.classInput()));
29
-
30
- protected readonly charCount = computed(() => {
31
- const text = this.getPlainText();
32
- return text.length;
33
- });
34
-
35
- private getPlainText(): string {
36
- const editorInstance = this.editor.editorInstance();
37
- if (editorInstance) {
38
- return editorInstance.getText();
39
- }
40
- return this.editor.contentElement()?.textContent || '';
41
- }
42
- }
@@ -1,42 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-clear-formatting]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-clear-formatting',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.title]': '"Clear formatting"',
23
- '(click)': 'onClick()',
24
- },
25
- encapsulation: ViewEncapsulation.None,
26
- changeDetection: ChangeDetectionStrategy.OnPush,
27
- })
28
- export class ScEditorClearFormattingButton {
29
- readonly editor = inject(SC_EDITOR);
30
- readonly classInput = input<string>('', { alias: 'class' });
31
-
32
- protected readonly class = computed(() =>
33
- cn(
34
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
35
- this.classInput(),
36
- ),
37
- );
38
-
39
- onClick(): void {
40
- this.editor.execCommand('removeFormat');
41
- }
42
- }
@@ -1,52 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-code]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-code',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.title]': '"Inline code"',
23
- '(click)': 'onClick()',
24
- },
25
- encapsulation: ViewEncapsulation.None,
26
- changeDetection: ChangeDetectionStrategy.OnPush,
27
- })
28
- export class ScEditorCodeButton {
29
- readonly editor = inject(SC_EDITOR);
30
- readonly classInput = input<string>('', { alias: 'class' });
31
-
32
- protected readonly class = computed(() =>
33
- cn(
34
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
35
- this.classInput(),
36
- ),
37
- );
38
-
39
- onClick(): void {
40
- if (this.editor.disabled() || this.editor.readonly()) return;
41
-
42
- const selection = window.getSelection();
43
- const selectedText = selection?.toString() || '';
44
-
45
- if (selectedText) {
46
- const code = `<code>${selectedText}</code>`;
47
- this.editor.execCommand('insertHTML', code);
48
- } else {
49
- this.editor.execCommand('insertHTML', '<code>&nbsp;</code>');
50
- }
51
- }
52
- }
@@ -1,107 +0,0 @@
1
- import {
2
- afterNextRender,
3
- ChangeDetectionStrategy,
4
- Component,
5
- computed,
6
- DestroyRef,
7
- effect,
8
- ElementRef,
9
- inject,
10
- input,
11
- model,
12
- output,
13
- signal,
14
- ViewEncapsulation,
15
- } from '@angular/core';
16
- import { cn } from '@semantic-components/ui';
17
- import { SC_EDITOR } from './editor';
18
-
19
- @Component({
20
- selector: 'div[sc-editor-content]',
21
- template: ``, // Empty - host element is the content div
22
- host: {
23
- 'data-slot': 'editor-content',
24
- '[class]': 'class()',
25
- '[attr.aria-label]': 'ariaLabel()',
26
- },
27
- encapsulation: ViewEncapsulation.None,
28
- changeDetection: ChangeDetectionStrategy.OnPush,
29
- })
30
- export class ScEditorContent {
31
- readonly editor = inject(SC_EDITOR);
32
- private readonly elementRef = inject(ElementRef<HTMLElement>);
33
- private readonly destroyRef = inject(DestroyRef);
34
-
35
- readonly value = model<string>('');
36
- readonly placeholder = input<string>('Start typing...');
37
- readonly ariaLabel = input<string>('Rich text editor');
38
- readonly classInput = input<string>('', { alias: 'class' });
39
-
40
- readonly focus = output<void>();
41
- readonly blur = output<void>();
42
-
43
- private readonly isFocused = signal(false);
44
- private isInitialized = false;
45
-
46
- protected readonly class = computed(() =>
47
- cn(
48
- 'block outline-none overflow-y-auto min-h-[150px] max-h-[400px] p-4 prose prose-sm max-w-none dark:prose-invert',
49
- this.editor.disabled() && 'pointer-events-none opacity-50',
50
- this.editor.readonly() && 'cursor-default',
51
- this.classInput(),
52
- ),
53
- );
54
-
55
- constructor() {
56
- // Watch for external value changes (must be in constructor for injection context)
57
- effect(() => {
58
- const newValue = this.value();
59
- const editorInstance = this.editor.editorInstance();
60
- if (!editorInstance || !this.isInitialized) return;
61
-
62
- const currentValue = editorInstance.getHTML();
63
-
64
- if (newValue !== currentValue) {
65
- editorInstance.commands.setContent(newValue);
66
- }
67
- });
68
-
69
- afterNextRender(() => {
70
- const element = this.elementRef.nativeElement;
71
-
72
- // Initialize Tiptap editor through parent directive
73
- this.editor.initializeEditor(element, this.value(), this.placeholder());
74
-
75
- // Watch for editor content changes
76
- const editorInstance = this.editor.editorInstance();
77
- if (editorInstance) {
78
- editorInstance.on('update', ({ editor }) => {
79
- const html = editor.getHTML();
80
- // Clean up empty content
81
- const cleaned = html === '<p></p>' ? '' : html;
82
-
83
- if (cleaned !== this.value()) {
84
- this.value.set(cleaned);
85
- }
86
- });
87
-
88
- // Handle focus events
89
- editorInstance.on('focus', () => {
90
- this.isFocused.set(true);
91
- this.focus.emit();
92
- });
93
-
94
- editorInstance.on('blur', () => {
95
- this.isFocused.set(false);
96
- this.blur.emit();
97
- });
98
- }
99
-
100
- this.isInitialized = true;
101
- });
102
-
103
- this.destroyRef.onDestroy(() => {
104
- this.editor.destroyEditor();
105
- });
106
- }
107
- }
@@ -1,28 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- ViewEncapsulation,
7
- } from '@angular/core';
8
- import { cn } from '@semantic-components/ui';
9
-
10
- @Component({
11
- selector: 'div[sc-editor-count]',
12
- template: `
13
- <ng-content />
14
- `,
15
- host: {
16
- 'data-slot': 'editor-count',
17
- '[class]': 'class()',
18
- },
19
- encapsulation: ViewEncapsulation.None,
20
- changeDetection: ChangeDetectionStrategy.OnPush,
21
- })
22
- export class ScEditorCount {
23
- readonly classInput = input<string>('', { alias: 'class' });
24
-
25
- protected readonly class = computed(() =>
26
- cn('flex items-center justify-end gap-4', this.classInput()),
27
- );
28
- }
@@ -1,30 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- ViewEncapsulation,
7
- } from '@angular/core';
8
- import { cn } from '@semantic-components/ui';
9
-
10
- @Component({
11
- selector: 'div[sc-editor-footer]',
12
- template: `
13
- <ng-content />
14
- `,
15
- host: {
16
- 'data-slot': 'editor-footer',
17
- '[class]': 'class()',
18
- },
19
- encapsulation: ViewEncapsulation.None,
20
- changeDetection: ChangeDetectionStrategy.OnPush,
21
- })
22
- export class ScEditorFooter {
23
- readonly classInput = input<string>('', { alias: 'class' });
24
- protected readonly class = computed(() =>
25
- cn(
26
- 'px-3 py-1.5 border-t text-xs text-muted-foreground bg-muted/30',
27
- this.classInput(),
28
- ),
29
- );
30
- }
@@ -1,27 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- ViewEncapsulation,
7
- } from '@angular/core';
8
- import { cn } from '@semantic-components/ui';
9
-
10
- @Component({
11
- selector: 'div[sc-editor-header]',
12
- template: `
13
- <ng-content />
14
- `,
15
- host: {
16
- 'data-slot': 'editor-header',
17
- '[class]': 'class()',
18
- },
19
- encapsulation: ViewEncapsulation.None,
20
- changeDetection: ChangeDetectionStrategy.OnPush,
21
- })
22
- export class ScEditorHeader {
23
- readonly classInput = input<string>('', { alias: 'class' });
24
- protected readonly class = computed(() =>
25
- cn('px-4 py-3 border-b bg-muted/30', this.classInput()),
26
- );
27
- }
@@ -1,48 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR, ScEditorHeading } from './editor';
11
-
12
- @Component({
13
- selector: 'select[sc-editor-heading]',
14
- template: `
15
- <option value="p">Paragraph</option>
16
- <option value="h1">Heading 1</option>
17
- <option value="h2">Heading 2</option>
18
- <option value="h3">Heading 3</option>
19
- <option value="h4">Heading 4</option>
20
- <option value="h5">Heading 5</option>
21
- <option value="h6">Heading 6</option>
22
- `,
23
- host: {
24
- 'data-slot': 'editor-heading',
25
- '[class]': 'class()',
26
- '[disabled]': 'editor.disabled()',
27
- '[value]': 'editor.currentHeading()',
28
- '(change)': 'onChange($event)',
29
- },
30
- encapsulation: ViewEncapsulation.None,
31
- changeDetection: ChangeDetectionStrategy.OnPush,
32
- })
33
- export class ScEditorHeadingSelect {
34
- readonly editor = inject(SC_EDITOR);
35
- readonly classInput = input<string>('', { alias: 'class' });
36
-
37
- protected readonly class = computed(() =>
38
- cn(
39
- 'appearance-none pl-2 pr-6 py-1 text-sm rounded border-0 bg-transparent hover:bg-accent cursor-pointer',
40
- this.classInput(),
41
- ),
42
- );
43
-
44
- onChange(event: Event): void {
45
- const value = (event.target as HTMLSelectElement).value as ScEditorHeading;
46
- this.editor.execCommand('formatBlock', value === 'p' ? 'p' : value);
47
- }
48
- }
@@ -1,42 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-horizontal-rule]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-horizontal-rule',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.title]': '"Horizontal line"',
23
- '(click)': 'onClick()',
24
- },
25
- encapsulation: ViewEncapsulation.None,
26
- changeDetection: ChangeDetectionStrategy.OnPush,
27
- })
28
- export class ScEditorHorizontalRuleButton {
29
- readonly editor = inject(SC_EDITOR);
30
- readonly classInput = input<string>('', { alias: 'class' });
31
-
32
- protected readonly class = computed(() =>
33
- cn(
34
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
35
- this.classInput(),
36
- ),
37
- );
38
-
39
- onClick(): void {
40
- this.editor.execCommand('insertHorizontalRule');
41
- }
42
- }
@@ -1,44 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-italic]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-italic',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.aria-pressed]': 'editor.isItalic()',
23
- '[attr.title]': '"Italic (Ctrl+I)"',
24
- '(click)': 'onClick()',
25
- },
26
- encapsulation: ViewEncapsulation.None,
27
- changeDetection: ChangeDetectionStrategy.OnPush,
28
- })
29
- export class ScEditorItalicButton {
30
- readonly editor = inject(SC_EDITOR);
31
- readonly classInput = input<string>('', { alias: 'class' });
32
-
33
- protected readonly class = computed(() =>
34
- cn(
35
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
36
- this.editor.isItalic() && 'bg-accent text-accent-foreground',
37
- this.classInput(),
38
- ),
39
- );
40
-
41
- onClick(): void {
42
- this.editor.execCommand('italic');
43
- }
44
- }
@@ -1,58 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-link]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-link',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.title]': '"Insert link (Ctrl+K)"',
23
- '(click)': 'onClick()',
24
- },
25
- encapsulation: ViewEncapsulation.None,
26
- changeDetection: ChangeDetectionStrategy.OnPush,
27
- })
28
- export class ScEditorLinkButton {
29
- readonly editor = inject(SC_EDITOR);
30
- readonly classInput = input<string>('', { alias: 'class' });
31
-
32
- protected readonly class = computed(() =>
33
- cn(
34
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
35
- this.classInput(),
36
- ),
37
- );
38
-
39
- onClick(): void {
40
- if (this.editor.disabled() || this.editor.readonly()) return;
41
-
42
- const selection = window.getSelection();
43
- const selectedText = selection?.toString() || '';
44
-
45
- const url = prompt('Enter URL:', 'https://');
46
- if (url) {
47
- if (selectedText) {
48
- this.editor.execCommand('createLink', url);
49
- } else {
50
- const linkText = prompt('Enter link text:', 'Link');
51
- if (linkText) {
52
- const link = `<a href="${url}" target="_blank" rel="noopener noreferrer">${linkText}</a>`;
53
- this.editor.execCommand('insertHTML', link);
54
- }
55
- }
56
- }
57
- }
58
- }
@@ -1,44 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-numbered-list]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-numbered-list',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.aria-pressed]': 'editor.isOrderedList()',
23
- '[attr.title]': '"Numbered list"',
24
- '(click)': 'onClick()',
25
- },
26
- encapsulation: ViewEncapsulation.None,
27
- changeDetection: ChangeDetectionStrategy.OnPush,
28
- })
29
- export class ScEditorNumberedListButton {
30
- readonly editor = inject(SC_EDITOR);
31
- readonly classInput = input<string>('', { alias: 'class' });
32
-
33
- protected readonly class = computed(() =>
34
- cn(
35
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
36
- this.editor.isOrderedList() && 'bg-accent text-accent-foreground',
37
- this.classInput(),
38
- ),
39
- );
40
-
41
- onClick(): void {
42
- this.editor.execCommand('insertOrderedList');
43
- }
44
- }
@@ -1,42 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-redo]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-redo',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled() || !editor.canRedo()',
22
- '[attr.title]': '"Redo (Ctrl+Y)"',
23
- '(click)': 'onClick()',
24
- },
25
- encapsulation: ViewEncapsulation.None,
26
- changeDetection: ChangeDetectionStrategy.OnPush,
27
- })
28
- export class ScEditorRedoButton {
29
- readonly editor = inject(SC_EDITOR);
30
- readonly classInput = input<string>('', { alias: 'class' });
31
-
32
- protected readonly class = computed(() =>
33
- cn(
34
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
35
- this.classInput(),
36
- ),
37
- );
38
-
39
- onClick(): void {
40
- this.editor.execCommand('redo');
41
- }
42
- }
@@ -1,25 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- ViewEncapsulation,
7
- } from '@angular/core';
8
- import { cn } from '@semantic-components/ui';
9
-
10
- @Component({
11
- selector: 'div[sc-editor-separator]',
12
- template: ``,
13
- host: {
14
- 'data-slot': 'editor-separator',
15
- '[class]': 'class()',
16
- },
17
- encapsulation: ViewEncapsulation.None,
18
- changeDetection: ChangeDetectionStrategy.OnPush,
19
- })
20
- export class ScEditorSeparator {
21
- readonly classInput = input<string>('', { alias: 'class' });
22
- protected readonly class = computed(() =>
23
- cn('w-px h-6 bg-border mx-1', this.classInput()),
24
- );
25
- }
@@ -1,44 +0,0 @@
1
- import {
2
- Component,
3
- ChangeDetectionStrategy,
4
- computed,
5
- input,
6
- inject,
7
- ViewEncapsulation,
8
- } from '@angular/core';
9
- import { cn } from '@semantic-components/ui';
10
- import { SC_EDITOR } from './editor';
11
-
12
- @Component({
13
- selector: 'button[sc-editor-strikethrough]',
14
- template: `
15
- <ng-content />
16
- `,
17
- host: {
18
- 'data-slot': 'editor-strikethrough',
19
- type: 'button',
20
- '[class]': 'class()',
21
- '[disabled]': 'editor.disabled()',
22
- '[attr.aria-pressed]': 'editor.isStrikethrough()',
23
- '[attr.title]': '"Strikethrough"',
24
- '(click)': 'onClick()',
25
- },
26
- encapsulation: ViewEncapsulation.None,
27
- changeDetection: ChangeDetectionStrategy.OnPush,
28
- })
29
- export class ScEditorStrikethroughButton {
30
- readonly editor = inject(SC_EDITOR);
31
- readonly classInput = input<string>('', { alias: 'class' });
32
-
33
- protected readonly class = computed(() =>
34
- cn(
35
- 'p-1.5 rounded hover:bg-accent disabled:opacity-50 [&_svg]:size-4',
36
- this.editor.isStrikethrough() && 'bg-accent text-accent-foreground',
37
- this.classInput(),
38
- ),
39
- );
40
-
41
- onClick(): void {
42
- this.editor.execCommand('strikethrough');
43
- }
44
- }