Skip to content

Commit bcf1ea3

Browse files
committed
refactor: use TypeScript
1 parent 6c64f54 commit bcf1ea3

16 files changed

+671
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import heading1css from '@utrecht/heading-1-css/dist/index.mjs';
2+
import heading2css from '@utrecht/heading-2-css/dist/index.mjs';
3+
import heading3css from '@utrecht/heading-3-css/dist/index.mjs';
4+
import heading4css from '@utrecht/heading-4-css/dist/index.mjs';
5+
import heading5css from '@utrecht/heading-5-css/dist/index.mjs';
6+
import heading6css from '@utrecht/heading-6-css/dist/index.mjs';
7+
8+
const stylesheet = new CSSStyleSheet();
9+
stylesheet.replaceSync([heading1css, heading2css, heading3css, heading4css, heading5css, heading6css].join(''));
10+
11+
const hostStylesheet = new CSSStyleSheet();
12+
hostStylesheet.replaceSync(`:host { display: block; }`);
13+
14+
export class UtrechtHeading extends HTMLElement {
15+
static observedAttributes = ['level'];
16+
shadow: ShadowRoot;
17+
constructor() {
18+
super();
19+
this.shadow = this.attachShadow({ mode: 'closed' });
20+
this.shadow.adoptedStyleSheets.push(stylesheet, hostStylesheet);
21+
this.rerender();
22+
}
23+
attributeChangedCallback(name: string) {
24+
if (name === 'level') {
25+
this.rerender();
26+
}
27+
}
28+
rerender() {
29+
while (this.shadow.firstChild) {
30+
this.shadow.removeChild(this.shadow.firstChild);
31+
}
32+
33+
const level = this.getAttribute('level');
34+
35+
let container;
36+
if (level) {
37+
container = this.ownerDocument.createElement(`h${level}`);
38+
container.classList.add(`utrecht-heading-${level}`);
39+
} else {
40+
container = this.ownerDocument.createElement('div');
41+
}
42+
43+
const slot = this.ownerDocument.createElement('slot');
44+
container.appendChild(slot);
45+
this.shadow.appendChild(container);
46+
}
47+
}
48+
49+
export const defineUtrechtHeading = () => customElements.define('utrecht-heading', UtrechtHeading);
50+
51+
export const defineCustomElements = defineUtrechtHeading;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import css from '@utrecht/ordered-list-css/dist/index.mjs';
2+
3+
const stylesheet = new CSSStyleSheet();
4+
stylesheet.replaceSync(css);
5+
const hostStylesheet = new CSSStyleSheet();
6+
hostStylesheet.replaceSync(`:host { display: contents; }`);
7+
8+
export class UtrechtOrderedListItem extends HTMLElement {
9+
shadow: ShadowRoot;
10+
constructor() {
11+
super();
12+
this.shadow = this.attachShadow({ mode: 'closed' });
13+
this.shadow.adoptedStyleSheets.push(hostStylesheet);
14+
this.shadow.adoptedStyleSheets.push(stylesheet);
15+
const li = this.ownerDocument.createElement('li');
16+
li.classList.add('utrecht-ordered-list__item');
17+
const slot = this.ownerDocument.createElement('slot');
18+
li.appendChild(slot);
19+
this.shadow.appendChild(li);
20+
}
21+
}
22+
23+
export const defineUtrechtOrderedListItem = () =>
24+
customElements.define('utrecht-ordered-list-item', UtrechtOrderedListItem);
25+
26+
export const defineCustomElements = defineUtrechtOrderedListItem;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import css from '@utrecht/ordered-list-css/dist/index.mjs';
2+
3+
const stylesheet = new CSSStyleSheet();
4+
stylesheet.replaceSync(css);
5+
const hostStylesheet = new CSSStyleSheet();
6+
hostStylesheet.replaceSync(`:host { display: contents; }`);
7+
8+
export class UtrechtOrderedList extends HTMLElement {
9+
shadow: ShadowRoot;
10+
constructor() {
11+
super();
12+
this.shadow = this.attachShadow({ mode: 'closed' });
13+
this.shadow.adoptedStyleSheets.push(hostStylesheet);
14+
this.shadow.adoptedStyleSheets.push(stylesheet);
15+
const ol = this.ownerDocument.createElement('ol');
16+
ol.classList.add('utrecht-ordered-list');
17+
ol.classList.add('utrecht-ordered-list--html-ol');
18+
const slot = this.ownerDocument.createElement('slot');
19+
ol.appendChild(slot);
20+
this.shadow.appendChild(ol);
21+
}
22+
}
23+
24+
export const defineUtrechtOrderedList = () => customElements.define('utrecht-ordered-list', UtrechtOrderedList);
25+
26+
export const defineCustomElements = defineUtrechtOrderedList;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import css from '@utrecht/paragraph-css/dist/index.mjs';
2+
3+
const stylesheet = new CSSStyleSheet();
4+
stylesheet.replaceSync(css);
5+
6+
export class UtrechtParagraph extends HTMLElement {
7+
shadow: ShadowRoot;
8+
constructor() {
9+
super();
10+
this.shadow = this.attachShadow({ mode: 'closed' });
11+
this.shadow.adoptedStyleSheets.push(stylesheet);
12+
const p = this.ownerDocument.createElement('p');
13+
p.classList.add('utrecht-paragraph');
14+
const slot = this.ownerDocument.createElement('slot');
15+
p.appendChild(slot);
16+
this.shadow.appendChild(p);
17+
}
18+
}
19+
20+
export const defineUtrechtParagraph = () => customElements.define('utrecht-paragraph', UtrechtParagraph);
21+
22+
export const defineCustomElements = defineUtrechtParagraph;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import css from '@utrecht/table-css/dist/index.mjs';
2+
3+
const stylesheet = new CSSStyleSheet();
4+
stylesheet.replaceSync(css);
5+
6+
export class UtrechtTableContainer extends HTMLElement {
7+
constructor() {
8+
super();
9+
if (!this.ownerDocument.adoptedStyleSheets.includes(stylesheet)) {
10+
this.ownerDocument.adoptedStyleSheets.push(stylesheet);
11+
}
12+
this.classList.add('utrecht-table-container');
13+
}
14+
}
15+
16+
export const defineUtrechtTableContainer = () =>
17+
customElements.define('utrecht-table-container', UtrechtTableContainer);
18+
19+
export const defineCustomElements = defineUtrechtTableContainer;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import css from '@utrecht/unordered-list-css/dist/index.mjs';
2+
3+
const stylesheet = new CSSStyleSheet();
4+
stylesheet.replaceSync(css);
5+
const hostStylesheet = new CSSStyleSheet();
6+
hostStylesheet.replaceSync(`:host { display: contents; }`);
7+
8+
export class UtrechtUnorderedListItem extends HTMLElement {
9+
shadow: ShadowRoot;
10+
constructor() {
11+
super();
12+
this.shadow = this.attachShadow({ mode: 'closed' });
13+
this.shadow.adoptedStyleSheets.push(hostStylesheet);
14+
this.shadow.adoptedStyleSheets.push(stylesheet);
15+
const li = this.ownerDocument.createElement('li');
16+
li.classList.add('utrecht-unordered-list__item');
17+
const slot = this.ownerDocument.createElement('slot');
18+
li.appendChild(slot);
19+
this.shadow.appendChild(li);
20+
}
21+
}
22+
23+
export const defineUtrechtUnorderedListItem = () =>
24+
customElements.define('utrecht-unordered-list-item', UtrechtUnorderedListItem);
25+
26+
export const defineCustomElements = defineUtrechtUnorderedListItem;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import css from '@utrecht/unordered-list-css/dist/index.mjs';
2+
3+
const stylesheet = new CSSStyleSheet();
4+
stylesheet.replaceSync(css);
5+
const hostStylesheet = new CSSStyleSheet();
6+
hostStylesheet.replaceSync(`:host { display: contents; }`);
7+
8+
export class UtrechtUnorderedList extends HTMLElement {
9+
shadow: ShadowRoot;
10+
constructor() {
11+
super();
12+
this.shadow = this.attachShadow({ mode: 'closed' });
13+
this.shadow.adoptedStyleSheets.push(hostStylesheet);
14+
this.shadow.adoptedStyleSheets.push(stylesheet);
15+
const ul = this.ownerDocument.createElement('ul');
16+
ul.classList.add('utrecht-unordered-list');
17+
ul.classList.add('utrecht-unordered-list--html-ul');
18+
const slot = this.ownerDocument.createElement('slot');
19+
ul.appendChild(slot);
20+
this.shadow.appendChild(ul);
21+
}
22+
}
23+
24+
export const defineUtrechtUnorderedList = () => customElements.define('utrecht-unordered-list', UtrechtUnorderedList);
25+
26+
export const defineCustomElements = defineUtrechtUnorderedList;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Node } from '@tiptap/core';
2+
3+
export const Document = Node.create({
4+
content: 'block+',
5+
name: 'document',
6+
topNode: true,
7+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Editor } from '@tiptap/core';
2+
import { Bold } from './bold.js';
3+
import { DataListItem } from './data-list-item.js';
4+
import { DataListKey } from './data-list-key.js';
5+
import { DataListValue } from './data-list-value.js';
6+
import { DataList } from './data-list.js';
7+
import { Document } from './document.js';
8+
import { Emphasis } from './emphasis.js';
9+
import { Heading } from './heading.js';
10+
import { Image } from './image.js';
11+
import { Italic } from './italic.js';
12+
import { Link } from './link.js';
13+
import { OrderedListItem } from './ordered-list-item.js';
14+
import { OrderedList } from './ordered-list.js';
15+
import { Paragraph } from './paragraph.js';
16+
import { Strong } from './strong.js';
17+
import { TableCaption } from './table-caption.js';
18+
import { TableCell } from './table-cell.js';
19+
import { TableHeaderCell } from './table-header-cell.js';
20+
import { TableRow } from './table-row.js';
21+
import { Table } from './table.js';
22+
import { Text } from './text.js';
23+
import { Underline } from './underline.js';
24+
import { UnorderedListItem } from './unordered-list-item.js';
25+
import { UnorderedList } from './unordered-list.js';
26+
import { Validation } from './validation.js';
27+
28+
class ExampleEditorElement extends HTMLElement {
29+
editor: Editor;
30+
constructor() {
31+
super();
32+
const defaultContent = '<utrecht-paragraph></utrecht-paragraph>';
33+
const template = this.querySelector('template');
34+
const content = template ? template.innerHTML : defaultContent;
35+
36+
this.editor = new Editor({
37+
element: this,
38+
extensions: [
39+
Bold,
40+
DataList,
41+
DataListItem,
42+
DataListKey,
43+
DataListValue,
44+
Document,
45+
Emphasis,
46+
Heading,
47+
Italic,
48+
Link,
49+
OrderedList,
50+
OrderedListItem,
51+
Image,
52+
Paragraph,
53+
Strong,
54+
Text,
55+
Table,
56+
TableCaption,
57+
TableHeaderCell,
58+
TableCell,
59+
TableRow,
60+
Underline,
61+
UnorderedList,
62+
UnorderedListItem,
63+
Validation,
64+
],
65+
content,
66+
});
67+
}
68+
}
69+
70+
export const defineExampleEditorElement = () => customElements.define('example-editor', ExampleEditorElement);
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { mergeAttributes, Node, textblockTypeInputRule } from '@tiptap/core';
2+
3+
export interface HeadingOptions {
4+
levels: number[];
5+
HTMLAttributes: Record<string, any>;
6+
}
7+
8+
declare module '@tiptap/core' {
9+
interface Commands<ReturnType> {
10+
heading: {
11+
setHeading: (options?: { level?: number }) => ReturnType;
12+
toggleHeading: (options?: { level?: number }) => ReturnType;
13+
};
14+
}
15+
}
16+
17+
export const Heading = Node.create<HeadingOptions>({
18+
name: 'heading',
19+
20+
addOptions() {
21+
return {
22+
levels: [1, 2, 3, 4, 5, 6, 7],
23+
HTMLAttributes: {},
24+
};
25+
},
26+
27+
content: 'inline*',
28+
29+
group: 'block',
30+
31+
defining: true,
32+
33+
addAttributes() {
34+
return {
35+
level: {
36+
default: 1,
37+
rendered: false,
38+
},
39+
};
40+
},
41+
42+
parseHTML() {
43+
return this.options.levels.map((level) => ({
44+
tag: 'utrecht-heading',
45+
attrs: { level },
46+
}));
47+
},
48+
49+
renderHTML({ node, HTMLAttributes }) {
50+
const hasLevel = this.options.levels.includes(node.attrs['level']);
51+
const level = hasLevel ? node.attrs['level'] : this.options.levels[0];
52+
53+
return ['utrecht-heading', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, { level }), 0];
54+
},
55+
56+
addCommands() {
57+
return {
58+
setHeading:
59+
(attributes) =>
60+
({ commands }) => {
61+
if (!(attributes?.level && this.options.levels.includes(attributes.level))) {
62+
return false;
63+
}
64+
65+
return commands.setNode(this.name, attributes);
66+
},
67+
toggleHeading:
68+
(attributes) =>
69+
({ commands }) => {
70+
if (!(attributes?.level && this.options.levels.includes(attributes.level))) {
71+
return false;
72+
}
73+
74+
return commands.toggleNode(this.name, 'paragraph', attributes);
75+
},
76+
};
77+
},
78+
79+
addKeyboardShortcuts() {
80+
return this.options.levels.reduce(
81+
(items, level) => ({
82+
...items,
83+
...{
84+
[`Mod-Alt-${level}`]: () => this.editor.commands.toggleHeading({ level }),
85+
},
86+
}),
87+
{},
88+
);
89+
},
90+
91+
addInputRules() {
92+
return this.options.levels.map((level) => {
93+
return textblockTypeInputRule({
94+
find: new RegExp(`^(#{${Math.min(...this.options.levels)},${level}})\\s$`),
95+
type: this.type,
96+
getAttributes: {
97+
level,
98+
},
99+
});
100+
});
101+
},
102+
});

0 commit comments

Comments
 (0)