@k2b/ui 0.18.0 → 0.19.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.
- package/README.md +3 -2
- package/dist/browser/actions/ContextMenu.js +3 -1
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/Dropdown.js +91 -46
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/FilterChip.js +4 -1
- package/dist/browser/actions/FilterChip.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +1293 -534
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/chat-behavior.js +9 -0
- package/dist/browser/chat/chat-behavior.js.map +1 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/chat/types.js.map +1 -1
- package/dist/browser/content/Calendar.js +579 -533
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/Lightbox.js +76 -40
- package/dist/browser/content/Lightbox.js.map +1 -1
- package/dist/browser/content/PdfPreview.js +146 -79
- package/dist/browser/content/PdfPreview.js.map +1 -1
- package/dist/browser/content/Timeline.js +1038 -0
- package/dist/browser/content/Timeline.js.map +1 -0
- package/dist/browser/content/VideoPlayer.js +29 -9
- package/dist/browser/content/VideoPlayer.js.map +1 -1
- package/dist/browser/content/chart-inspection.js +7 -2
- package/dist/browser/content/chart-inspection.js.map +1 -1
- package/dist/browser/content/index.js +1 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/content/timeline-model.js +579 -0
- package/dist/browser/content/timeline-model.js.map +1 -0
- package/dist/browser/feedback/dialog-core.js +26 -14
- package/dist/browser/feedback/dialog-core.js.map +1 -1
- package/dist/browser/inputs/ChoiceChips.js +66 -0
- package/dist/browser/inputs/ChoiceChips.js.map +1 -0
- package/dist/browser/inputs/ChoiceGroups.js +53 -12
- package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
- package/dist/browser/inputs/FileInputs.js +48 -33
- package/dist/browser/inputs/FileInputs.js.map +1 -1
- package/dist/browser/inputs/SignatureInput.js +558 -0
- package/dist/browser/inputs/SignatureInput.js.map +1 -0
- package/dist/browser/inputs/emoji/EmojiPicker.js +841 -0
- package/dist/browser/inputs/emoji/EmojiPicker.js.map +1 -0
- package/dist/browser/inputs/emoji/emoji-data.js +1903 -0
- package/dist/browser/inputs/emoji/emoji-data.js.map +1 -0
- package/dist/browser/inputs/emoji/emoji-index.js +209 -0
- package/dist/browser/inputs/emoji/emoji-index.js.map +1 -0
- package/dist/browser/inputs/emoji/emoji-messages.js +64 -0
- package/dist/browser/inputs/emoji/emoji-messages.js.map +1 -0
- package/dist/browser/inputs/index.js +5 -0
- package/dist/browser/inputs/index.js.map +1 -1
- package/dist/browser/inputs/markdown/actions.js +48 -2
- package/dist/browser/inputs/markdown/actions.js.map +1 -1
- package/dist/browser/inputs/markdown/code-zone.js +38 -2
- package/dist/browser/inputs/markdown/code-zone.js.map +1 -1
- package/dist/browser/inputs/signature-messages.js +39 -0
- package/dist/browser/inputs/signature-messages.js.map +1 -0
- package/dist/browser/inputs/signature.js +208 -0
- package/dist/browser/inputs/signature.js.map +1 -0
- package/dist/browser/internal/render-error.js +49 -0
- package/dist/browser/internal/render-error.js.map +1 -0
- package/dist/browser/intl/messages.js +108 -0
- package/dist/browser/intl/messages.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +321 -222
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/FloatingWindow.js +4 -1
- package/dist/browser/layout/FloatingWindow.js.map +1 -1
- package/dist/browser/layout/SidebarItemPreview.js +5 -1
- package/dist/browser/layout/SidebarItemPreview.js.map +1 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/surfaces/ResourceCard.js +212 -0
- package/dist/browser/surfaces/ResourceCard.js.map +1 -0
- package/dist/browser/surfaces/index.js +1 -0
- package/dist/browser/surfaces/index.js.map +1 -1
- package/dist/licenses/emojibase-data.txt +21 -0
- package/dist/ssr/actions/ContextMenu.js +3 -1
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +49 -12
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/FilterChip.js +4 -1
- package/dist/ssr/actions/FilterChip.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +805 -214
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/chat-behavior.js +9 -0
- package/dist/ssr/chat/chat-behavior.js.map +1 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/chat/types.js.map +1 -1
- package/dist/ssr/content/Calendar.js +183 -142
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/Lightbox.js +19 -5
- package/dist/ssr/content/Lightbox.js.map +1 -1
- package/dist/ssr/content/PdfPreview.js +77 -36
- package/dist/ssr/content/PdfPreview.js.map +1 -1
- package/dist/ssr/content/Timeline.js +804 -0
- package/dist/ssr/content/Timeline.js.map +1 -0
- package/dist/ssr/content/VideoPlayer.js +29 -9
- package/dist/ssr/content/VideoPlayer.js.map +1 -1
- package/dist/ssr/content/chart-inspection.js +7 -2
- package/dist/ssr/content/chart-inspection.js.map +1 -1
- package/dist/ssr/content/index.js +1 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/content/timeline-model.js +579 -0
- package/dist/ssr/content/timeline-model.js.map +1 -0
- package/dist/ssr/feedback/dialog-core.js +26 -14
- package/dist/ssr/feedback/dialog-core.js.map +1 -1
- package/dist/ssr/inputs/ChoiceChips.js +66 -0
- package/dist/ssr/inputs/ChoiceChips.js.map +1 -0
- package/dist/ssr/inputs/ChoiceGroups.js +12 -4
- package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
- package/dist/ssr/inputs/FileInputs.js +19 -4
- package/dist/ssr/inputs/FileInputs.js.map +1 -1
- package/dist/ssr/inputs/SignatureInput.js +404 -0
- package/dist/ssr/inputs/SignatureInput.js.map +1 -0
- package/dist/ssr/inputs/emoji/EmojiPicker.js +551 -0
- package/dist/ssr/inputs/emoji/EmojiPicker.js.map +1 -0
- package/dist/ssr/inputs/emoji/emoji-data.js +1903 -0
- package/dist/ssr/inputs/emoji/emoji-data.js.map +1 -0
- package/dist/ssr/inputs/emoji/emoji-index.js +209 -0
- package/dist/ssr/inputs/emoji/emoji-index.js.map +1 -0
- package/dist/ssr/inputs/emoji/emoji-messages.js +64 -0
- package/dist/ssr/inputs/emoji/emoji-messages.js.map +1 -0
- package/dist/ssr/inputs/index.js +5 -0
- package/dist/ssr/inputs/index.js.map +1 -1
- package/dist/ssr/inputs/markdown/actions.js +48 -2
- package/dist/ssr/inputs/markdown/actions.js.map +1 -1
- package/dist/ssr/inputs/markdown/code-zone.js +38 -2
- package/dist/ssr/inputs/markdown/code-zone.js.map +1 -1
- package/dist/ssr/inputs/signature-messages.js +39 -0
- package/dist/ssr/inputs/signature-messages.js.map +1 -0
- package/dist/ssr/inputs/signature.js +208 -0
- package/dist/ssr/inputs/signature.js.map +1 -0
- package/dist/ssr/internal/render-error.js +49 -0
- package/dist/ssr/internal/render-error.js.map +1 -0
- package/dist/ssr/intl/messages.js +108 -0
- package/dist/ssr/intl/messages.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +112 -41
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/FloatingWindow.js +4 -1
- package/dist/ssr/layout/FloatingWindow.js.map +1 -1
- package/dist/ssr/layout/SidebarItemPreview.js +5 -1
- package/dist/ssr/layout/SidebarItemPreview.js.map +1 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/surfaces/ResourceCard.js +115 -0
- package/dist/ssr/surfaces/ResourceCard.js.map +1 -0
- package/dist/ssr/surfaces/index.js +1 -0
- package/dist/ssr/surfaces/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +13 -1
- package/dist/types/actions/FilterChip.d.ts +5 -0
- package/dist/types/chat/ChatComposer.d.ts +24 -1
- package/dist/types/chat/chat-behavior.d.ts +15 -0
- package/dist/types/chat/index.d.ts +1 -1
- package/dist/types/chat/types.d.ts +34 -0
- package/dist/types/content/Calendar.d.ts +28 -8
- package/dist/types/content/Lightbox.d.ts +8 -0
- package/dist/types/content/Timeline.d.ts +49 -0
- package/dist/types/content/index.d.ts +4 -2
- package/dist/types/content/timeline-model.d.ts +148 -0
- package/dist/types/feedback/dialog-core.d.ts +1 -1
- package/dist/types/inputs/ChoiceChips.d.ts +20 -0
- package/dist/types/inputs/ChoiceGroups.d.ts +11 -2
- package/dist/types/inputs/FileInputs.d.ts +6 -0
- package/dist/types/inputs/SignatureInput.d.ts +22 -0
- package/dist/types/inputs/emoji/EmojiPicker.d.ts +42 -0
- package/dist/types/inputs/emoji/emoji-data.d.ts +2 -0
- package/dist/types/inputs/emoji/emoji-index.d.ts +109 -0
- package/dist/types/inputs/emoji/emoji-messages.d.ts +30 -0
- package/dist/types/inputs/index.d.ts +10 -0
- package/dist/types/inputs/markdown/actions.d.ts +4 -0
- package/dist/types/inputs/markdown/code-zone.d.ts +7 -0
- package/dist/types/inputs/signature-messages.d.ts +11 -0
- package/dist/types/inputs/signature.d.ts +72 -0
- package/dist/types/internal/render-error.d.ts +13 -0
- package/dist/types/intl/messages.d.ts +54 -0
- package/dist/types/layout/AppWorkspace.d.ts +17 -0
- package/dist/types/layout/SidebarItemPreview.d.ts +2 -0
- package/dist/types/layout/index.d.ts +1 -1
- package/dist/types/surfaces/ResourceCard.d.ts +31 -0
- package/dist/types/surfaces/index.d.ts +2 -0
- package/package.json +5 -4
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The emoji dataset behind `EmojiPicker` and the composer's `:shortcode` completion. The data (about 80 kB compressed)
|
|
3
|
+
* loads on first use, so a page that never opens either does not download it.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { isInCodeZone } from "../markdown/code-zone";
|
|
7
|
+
|
|
8
|
+
/** `0` is the default yellow; `1` (light) to `5` (dark) are the Fitzpatrick modifiers. */
|
|
9
|
+
|
|
10
|
+
export const EMOJI_SKIN_TONES = [0, 1, 2, 3, 4, 5];
|
|
11
|
+
|
|
12
|
+
/** The groups in their order. Emojibase numbers them 0 to 9; 2 holds skin-tone parts and never appears. */
|
|
13
|
+
export const EMOJI_GROUPS = [{
|
|
14
|
+
id: 0,
|
|
15
|
+
key: "smileys",
|
|
16
|
+
icon: "ti ti-mood-smile"
|
|
17
|
+
}, {
|
|
18
|
+
id: 1,
|
|
19
|
+
key: "people",
|
|
20
|
+
icon: "ti ti-hand-stop"
|
|
21
|
+
}, {
|
|
22
|
+
id: 3,
|
|
23
|
+
key: "animals",
|
|
24
|
+
icon: "ti ti-paw"
|
|
25
|
+
}, {
|
|
26
|
+
id: 4,
|
|
27
|
+
key: "food",
|
|
28
|
+
icon: "ti ti-tools-kitchen-2"
|
|
29
|
+
}, {
|
|
30
|
+
id: 5,
|
|
31
|
+
key: "travel",
|
|
32
|
+
icon: "ti ti-plane"
|
|
33
|
+
}, {
|
|
34
|
+
id: 6,
|
|
35
|
+
key: "activities",
|
|
36
|
+
icon: "ti ti-ball-football"
|
|
37
|
+
}, {
|
|
38
|
+
id: 7,
|
|
39
|
+
key: "objects",
|
|
40
|
+
icon: "ti ti-bulb"
|
|
41
|
+
}, {
|
|
42
|
+
id: 8,
|
|
43
|
+
key: "symbols",
|
|
44
|
+
icon: "ti ti-heart"
|
|
45
|
+
}, {
|
|
46
|
+
id: 9,
|
|
47
|
+
key: "flags",
|
|
48
|
+
icon: "ti ti-flag"
|
|
49
|
+
}];
|
|
50
|
+
const LIGHT_TONE = "\u{1F3FB}";
|
|
51
|
+
const PRESENTATION_SELECTOR = /️/g;
|
|
52
|
+
|
|
53
|
+
/** Lower case without accents, so "lacheln", "laecheln" and "Lächeln" meet; `_` and `-` separate words. */
|
|
54
|
+
export const normalizeEmojiQuery = value => value.toLowerCase().normalize("NFD").replace(/\p{M}/gu, "").replace(/ß/g, "ss").replace(/[_\-\s]+/g, " ").trim();
|
|
55
|
+
|
|
56
|
+
/** German also gets its spelling without umlauts: "Lächeln" is found as "laecheln". */
|
|
57
|
+
const germanForms = value => {
|
|
58
|
+
const plain = normalizeEmojiQuery(value);
|
|
59
|
+
const spelled = normalizeEmojiQuery(value.toLowerCase().replace(/ä/g, "ae").replace(/ö/g, "oe").replace(/ü/g, "ue"));
|
|
60
|
+
return spelled === plain ? [plain] : [plain, spelled];
|
|
61
|
+
};
|
|
62
|
+
const list = value => value ? value.split("|") : [];
|
|
63
|
+
export const parseEmojiData = data => {
|
|
64
|
+
const entries = [];
|
|
65
|
+
const byEmoji = new Map();
|
|
66
|
+
const byShortcode = new Map();
|
|
67
|
+
for (const line of data.split("\n")) {
|
|
68
|
+
const [emoji, group, light, en, enKeywords, de, deKeywords, codes] = line.split("\t");
|
|
69
|
+
if (!emoji || !en || !de) continue;
|
|
70
|
+
const shortcodes = list(codes);
|
|
71
|
+
const names = [normalizeEmojiQuery(en), ...germanForms(de)];
|
|
72
|
+
const keywords = [...list(enKeywords).map(normalizeEmojiQuery), ...list(deKeywords).flatMap(germanForms)];
|
|
73
|
+
const normalizedCodes = shortcodes.map(normalizeEmojiQuery);
|
|
74
|
+
const entry = {
|
|
75
|
+
emoji,
|
|
76
|
+
group: Number(group),
|
|
77
|
+
light: light || undefined,
|
|
78
|
+
name: {
|
|
79
|
+
en,
|
|
80
|
+
de
|
|
81
|
+
},
|
|
82
|
+
shortcodes,
|
|
83
|
+
search: {
|
|
84
|
+
names,
|
|
85
|
+
keywords,
|
|
86
|
+
shortcodes: normalizedCodes,
|
|
87
|
+
words: [...new Set([...names, ...keywords, ...normalizedCodes].flatMap(term => term.split(" ")))]
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
entries.push(entry);
|
|
91
|
+
for (const variant of [emoji, ...EMOJI_SKIN_TONES.slice(1).map(tone => emojiInTone(entry, tone))]) {
|
|
92
|
+
byEmoji.set(variant.replace(PRESENTATION_SELECTOR, ""), entry);
|
|
93
|
+
}
|
|
94
|
+
for (const code of shortcodes) byShortcode.set(code.toLowerCase(), entry);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
entries,
|
|
98
|
+
byEmoji,
|
|
99
|
+
byShortcode
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
let loading;
|
|
103
|
+
|
|
104
|
+
/** Loads and indexes the dataset once. A failed load is retried on the next call. */
|
|
105
|
+
export const loadEmojiIndex = () => {
|
|
106
|
+
loading ??= import("./emoji-data").then(module => parseEmojiData(module.default), error => {
|
|
107
|
+
loading = undefined;
|
|
108
|
+
throw error;
|
|
109
|
+
});
|
|
110
|
+
return loading;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/** The entry of an emoji in any skin tone, with or without presentation selectors. */
|
|
114
|
+
export const findEmoji = (index, emoji) => index.byEmoji.get(emoji.replace(PRESENTATION_SELECTOR, ""));
|
|
115
|
+
|
|
116
|
+
/** The emoji in `tone`; emoji without skin tones stay as they are. */
|
|
117
|
+
export const emojiInTone = (entry, tone) => tone === 0 || !entry.light ? entry.emoji : entry.light.replaceAll(LIGHT_TONE, String.fromCodePoint(0x1f3fb + tone - 1));
|
|
118
|
+
|
|
119
|
+
/** The name in the render language: German for `de` locales, English otherwise. */
|
|
120
|
+
export const emojiName = (entry, locale) => /^de\b/i.test(locale) ? entry.name.de : entry.name.en;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Lower is better; `undefined` does not match. A shortcode's prefix beats a name's, so `:tad` finds 🎉 first. `infix`
|
|
124
|
+
* also matches letters inside a name, as the picker's search does.
|
|
125
|
+
*/
|
|
126
|
+
const rank = (entry, query, infix) => {
|
|
127
|
+
const {
|
|
128
|
+
names,
|
|
129
|
+
keywords,
|
|
130
|
+
shortcodes,
|
|
131
|
+
words
|
|
132
|
+
} = entry.search;
|
|
133
|
+
if (shortcodes.includes(query)) return 0;
|
|
134
|
+
if (names.includes(query)) return 1;
|
|
135
|
+
if (shortcodes.some(code => code.startsWith(query))) return 2;
|
|
136
|
+
if (names.some(name => name.startsWith(query))) return 3;
|
|
137
|
+
if (names.some(name => name.includes(` ${query}`))) return 4;
|
|
138
|
+
if (keywords.includes(query)) return 5;
|
|
139
|
+
if (keywords.some(keyword => keyword.startsWith(query))) return 6;
|
|
140
|
+
if (infix && names.some(name => name.includes(query))) return 7;
|
|
141
|
+
// Several words match when each starts a word of the entry: "hand up" finds "raising hand".
|
|
142
|
+
const terms = query.split(" ");
|
|
143
|
+
if (terms.length > 1 && terms.every(term => words.some(word => word.startsWith(term)))) return 8;
|
|
144
|
+
return undefined;
|
|
145
|
+
};
|
|
146
|
+
const ranked = (index, query, infix, limit) => {
|
|
147
|
+
if (!query) return [];
|
|
148
|
+
const matches = [];
|
|
149
|
+
index.entries.forEach((entry, position) => {
|
|
150
|
+
const value = rank(entry, query, infix);
|
|
151
|
+
if (value !== undefined) matches.push({
|
|
152
|
+
entry,
|
|
153
|
+
rank: value,
|
|
154
|
+
position
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
matches.sort((left, right) => left.rank - right.rank || left.position - right.position);
|
|
158
|
+
return matches.slice(0, limit).map(match => match.entry);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/** Matches in English and German names, keywords and shortcodes, best first and otherwise in Unicode order. */
|
|
162
|
+
export const searchEmoji = (index, query, limit = Number.POSITIVE_INFINITY) => ranked(index, normalizeEmojiQuery(query.replace(/^:+|:+$/g, "")), true, limit);
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The suggestions for a `:shortcode` being typed. Only the start of a shortcode, name, word or keyword counts, and a
|
|
166
|
+
* leading sign must start a shortcode, as in `:+1` and `:-1`: emoticons such as `:DD`, `:-D` or `:-P` find nothing,
|
|
167
|
+
* so Enter still sends them.
|
|
168
|
+
*/
|
|
169
|
+
export const suggestEmoji = (index, query, limit) => {
|
|
170
|
+
if (/^[+-]/.test(query)) {
|
|
171
|
+
const code = query.toLowerCase();
|
|
172
|
+
return index.entries.filter(entry => entry.shortcodes.some(shortcode => shortcode.startsWith(code))).slice(0, limit);
|
|
173
|
+
}
|
|
174
|
+
const normalized = normalizeEmojiQuery(query);
|
|
175
|
+
return normalized.length < 2 ? [] : ranked(index, normalized, false, limit);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/** As many recent emoji as the picker shows: three rows. */
|
|
179
|
+
export const RECENT_EMOJI_LIMIT = 24;
|
|
180
|
+
|
|
181
|
+
/** The recent list after `emoji` was used: it moves to the front, once, and the oldest drop off. */
|
|
182
|
+
export const rememberEmoji = (recent, emoji) => [emoji, ...recent.filter(item => item !== emoji)].slice(0, RECENT_EMOJI_LIMIT);
|
|
183
|
+
/**
|
|
184
|
+
* The `:shortcode` being typed at the caret: a colon at the start or after a space or "(", then at least two letters,
|
|
185
|
+
* digits, "_", "+" or "-". Code, URLs ("https://") and times ("10:30") are no queries.
|
|
186
|
+
*/
|
|
187
|
+
export const emojiShortcodeQuery = (text, caret, selectionEnd = caret) => {
|
|
188
|
+
if (caret !== selectionEnd || isInCodeZone(text, caret)) return null;
|
|
189
|
+
const match = /(?:^|[\s(]):([\p{L}\p{N}_+-]{2,})$/u.exec(text.slice(0, caret));
|
|
190
|
+
if (!match) return null;
|
|
191
|
+
return {
|
|
192
|
+
start: caret - match[1].length - 1,
|
|
193
|
+
end: caret,
|
|
194
|
+
query: match[1]
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/** A complete `:shortcode:` just typed at the caret, such as `:thumbsup:`, with its range. */
|
|
199
|
+
export const completedEmojiShortcode = (text, caret) => {
|
|
200
|
+
if (isInCodeZone(text, caret)) return null;
|
|
201
|
+
const match = /(?:^|[\s(]):([\p{L}\p{N}_+-]+):$/u.exec(text.slice(0, caret));
|
|
202
|
+
if (!match) return null;
|
|
203
|
+
return {
|
|
204
|
+
start: caret - match[1].length - 2,
|
|
205
|
+
end: caret,
|
|
206
|
+
shortcode: match[1]
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
//# sourceMappingURL=emoji-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/emoji/emoji-index.ts"],"sourcesContent":["/**\n * The emoji dataset behind `EmojiPicker` and the composer's `:shortcode` completion. The data (about 80 kB compressed)\n * loads on first use, so a page that never opens either does not download it.\n */\n\nimport { isInCodeZone } from \"../markdown/code-zone\";\n\n/** `0` is the default yellow; `1` (light) to `5` (dark) are the Fitzpatrick modifiers. */\nexport type EmojiSkinTone = 0 | 1 | 2 | 3 | 4 | 5;\n\nexport const EMOJI_SKIN_TONES: readonly EmojiSkinTone[] = [0, 1, 2, 3, 4, 5];\n\n/** The groups in their order. Emojibase numbers them 0 to 9; 2 holds skin-tone parts and never appears. */\nexport const EMOJI_GROUPS = [\n { id: 0, key: \"smileys\", icon: \"ti ti-mood-smile\" },\n { id: 1, key: \"people\", icon: \"ti ti-hand-stop\" },\n { id: 3, key: \"animals\", icon: \"ti ti-paw\" },\n { id: 4, key: \"food\", icon: \"ti ti-tools-kitchen-2\" },\n { id: 5, key: \"travel\", icon: \"ti ti-plane\" },\n { id: 6, key: \"activities\", icon: \"ti ti-ball-football\" },\n { id: 7, key: \"objects\", icon: \"ti ti-bulb\" },\n { id: 8, key: \"symbols\", icon: \"ti ti-heart\" },\n { id: 9, key: \"flags\", icon: \"ti ti-flag\" },\n] as const;\n\nexport type EmojiGroupKey = (typeof EMOJI_GROUPS)[number][\"key\"];\n\nexport type EmojiEntry = {\n emoji: string;\n group: number;\n /** The light variant; the other tones swap its modifier. Absent for emoji without skin tones. */\n light?: string;\n name: { en: string; de: string };\n shortcodes: readonly string[];\n /** Normalized names, keywords and shortcodes for search. */\n search: { names: readonly string[]; keywords: readonly string[]; shortcodes: readonly string[]; words: readonly string[] };\n};\n\nexport type EmojiIndex = {\n entries: readonly EmojiEntry[];\n /** Every emoji and skin-tone variant, without presentation selectors, to its entry. Look up with `findEmoji`. */\n byEmoji: ReadonlyMap<string, EmojiEntry>;\n byShortcode: ReadonlyMap<string, EmojiEntry>;\n};\n\nconst LIGHT_TONE = \"\\u{1F3FB}\";\nconst PRESENTATION_SELECTOR = /️/g;\n\n/** Lower case without accents, so \"lacheln\", \"laecheln\" and \"Lächeln\" meet; `_` and `-` separate words. */\nexport const normalizeEmojiQuery = (value: string): string =>\n value\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/\\p{M}/gu, \"\")\n .replace(/ß/g, \"ss\")\n .replace(/[_\\-\\s]+/g, \" \")\n .trim();\n\n/** German also gets its spelling without umlauts: \"Lächeln\" is found as \"laecheln\". */\nconst germanForms = (value: string): string[] => {\n const plain = normalizeEmojiQuery(value);\n const spelled = normalizeEmojiQuery(value.toLowerCase().replace(/ä/g, \"ae\").replace(/ö/g, \"oe\").replace(/ü/g, \"ue\"));\n return spelled === plain ? [plain] : [plain, spelled];\n};\n\nconst list = (value: string | undefined): string[] => (value ? value.split(\"|\") : []);\n\nexport const parseEmojiData = (data: string): EmojiIndex => {\n const entries: EmojiEntry[] = [];\n const byEmoji = new Map<string, EmojiEntry>();\n const byShortcode = new Map<string, EmojiEntry>();\n for (const line of data.split(\"\\n\")) {\n const [emoji, group, light, en, enKeywords, de, deKeywords, codes] = line.split(\"\\t\");\n if (!emoji || !en || !de) continue;\n const shortcodes = list(codes);\n const names = [normalizeEmojiQuery(en), ...germanForms(de)];\n const keywords = [...list(enKeywords).map(normalizeEmojiQuery), ...list(deKeywords).flatMap(germanForms)];\n const normalizedCodes = shortcodes.map(normalizeEmojiQuery);\n const entry: EmojiEntry = {\n emoji,\n group: Number(group),\n light: light || undefined,\n name: { en, de },\n shortcodes,\n search: {\n names,\n keywords,\n shortcodes: normalizedCodes,\n words: [...new Set([...names, ...keywords, ...normalizedCodes].flatMap((term) => term.split(\" \")))],\n },\n };\n entries.push(entry);\n for (const variant of [emoji, ...EMOJI_SKIN_TONES.slice(1).map((tone) => emojiInTone(entry, tone))]) {\n byEmoji.set(variant.replace(PRESENTATION_SELECTOR, \"\"), entry);\n }\n for (const code of shortcodes) byShortcode.set(code.toLowerCase(), entry);\n }\n return { entries, byEmoji, byShortcode };\n};\n\nlet loading: Promise<EmojiIndex> | undefined;\n\n/** Loads and indexes the dataset once. A failed load is retried on the next call. */\nexport const loadEmojiIndex = (): Promise<EmojiIndex> => {\n loading ??= import(\"./emoji-data\").then(\n (module) => parseEmojiData(module.default),\n (error: unknown) => {\n loading = undefined;\n throw error;\n },\n );\n return loading;\n};\n\n/** The entry of an emoji in any skin tone, with or without presentation selectors. */\nexport const findEmoji = (index: EmojiIndex, emoji: string): EmojiEntry | undefined =>\n index.byEmoji.get(emoji.replace(PRESENTATION_SELECTOR, \"\"));\n\n/** The emoji in `tone`; emoji without skin tones stay as they are. */\nexport const emojiInTone = (entry: EmojiEntry, tone: EmojiSkinTone): string =>\n tone === 0 || !entry.light ? entry.emoji : entry.light.replaceAll(LIGHT_TONE, String.fromCodePoint(0x1f3fb + tone - 1));\n\n/** The name in the render language: German for `de` locales, English otherwise. */\nexport const emojiName = (entry: EmojiEntry, locale: string): string => (/^de\\b/i.test(locale) ? entry.name.de : entry.name.en);\n\n/**\n * Lower is better; `undefined` does not match. A shortcode's prefix beats a name's, so `:tad` finds 🎉 first. `infix`\n * also matches letters inside a name, as the picker's search does.\n */\nconst rank = (entry: EmojiEntry, query: string, infix: boolean): number | undefined => {\n const { names, keywords, shortcodes, words } = entry.search;\n if (shortcodes.includes(query)) return 0;\n if (names.includes(query)) return 1;\n if (shortcodes.some((code) => code.startsWith(query))) return 2;\n if (names.some((name) => name.startsWith(query))) return 3;\n if (names.some((name) => name.includes(` ${query}`))) return 4;\n if (keywords.includes(query)) return 5;\n if (keywords.some((keyword) => keyword.startsWith(query))) return 6;\n if (infix && names.some((name) => name.includes(query))) return 7;\n // Several words match when each starts a word of the entry: \"hand up\" finds \"raising hand\".\n const terms = query.split(\" \");\n if (terms.length > 1 && terms.every((term) => words.some((word) => word.startsWith(term)))) return 8;\n return undefined;\n};\n\nconst ranked = (index: EmojiIndex, query: string, infix: boolean, limit: number): EmojiEntry[] => {\n if (!query) return [];\n const matches: { entry: EmojiEntry; rank: number; position: number }[] = [];\n index.entries.forEach((entry, position) => {\n const value = rank(entry, query, infix);\n if (value !== undefined) matches.push({ entry, rank: value, position });\n });\n matches.sort((left, right) => left.rank - right.rank || left.position - right.position);\n return matches.slice(0, limit).map((match) => match.entry);\n};\n\n/** Matches in English and German names, keywords and shortcodes, best first and otherwise in Unicode order. */\nexport const searchEmoji = (index: EmojiIndex, query: string, limit = Number.POSITIVE_INFINITY): EmojiEntry[] =>\n ranked(index, normalizeEmojiQuery(query.replace(/^:+|:+$/g, \"\")), true, limit);\n\n/**\n * The suggestions for a `:shortcode` being typed. Only the start of a shortcode, name, word or keyword counts, and a\n * leading sign must start a shortcode, as in `:+1` and `:-1`: emoticons such as `:DD`, `:-D` or `:-P` find nothing,\n * so Enter still sends them.\n */\nexport const suggestEmoji = (index: EmojiIndex, query: string, limit: number): EmojiEntry[] => {\n if (/^[+-]/.test(query)) {\n const code = query.toLowerCase();\n return index.entries.filter((entry) => entry.shortcodes.some((shortcode) => shortcode.startsWith(code))).slice(0, limit);\n }\n const normalized = normalizeEmojiQuery(query);\n return normalized.length < 2 ? [] : ranked(index, normalized, false, limit);\n};\n\n/** As many recent emoji as the picker shows: three rows. */\nexport const RECENT_EMOJI_LIMIT = 24;\n\n/** The recent list after `emoji` was used: it moves to the front, once, and the oldest drop off. */\nexport const rememberEmoji = (recent: readonly string[], emoji: string): string[] =>\n [emoji, ...recent.filter((item) => item !== emoji)].slice(0, RECENT_EMOJI_LIMIT);\n\nexport type EmojiShortcodeQuery = { start: number; end: number; query: string };\n\n/**\n * The `:shortcode` being typed at the caret: a colon at the start or after a space or \"(\", then at least two letters,\n * digits, \"_\", \"+\" or \"-\". Code, URLs (\"https://\") and times (\"10:30\") are no queries.\n */\nexport const emojiShortcodeQuery = (text: string, caret: number, selectionEnd = caret): EmojiShortcodeQuery | null => {\n if (caret !== selectionEnd || isInCodeZone(text, caret)) return null;\n const match = /(?:^|[\\s(]):([\\p{L}\\p{N}_+-]{2,})$/u.exec(text.slice(0, caret));\n if (!match) return null;\n return { start: caret - match[1]!.length - 1, end: caret, query: match[1]! };\n};\n\n/** A complete `:shortcode:` just typed at the caret, such as `:thumbsup:`, with its range. */\nexport const completedEmojiShortcode = (text: string, caret: number): { start: number; end: number; shortcode: string } | null => {\n if (isInCodeZone(text, caret)) return null;\n const match = /(?:^|[\\s(]):([\\p{L}\\p{N}_+-]+):$/u.exec(text.slice(0, caret));\n if (!match) return null;\n return { start: caret - match[1]!.length - 2, end: caret, shortcode: match[1]! };\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { i18n } from "@k2b/stdlib";
|
|
2
|
+
import { useLocale } from "../../intl/locale";
|
|
3
|
+
|
|
4
|
+
/** The picker's own strings. They live with the picker, so pages without it do not carry them. */
|
|
5
|
+
const emojiMessages = i18n.define({
|
|
6
|
+
baseLocale: "en",
|
|
7
|
+
messages: {
|
|
8
|
+
en: {
|
|
9
|
+
emojiPicker: "Emoji",
|
|
10
|
+
emojiSearch: "Search emoji",
|
|
11
|
+
emojiGroups: "Emoji groups",
|
|
12
|
+
emojiRecent: "Recently used",
|
|
13
|
+
emojiSmileys: "Smileys & emotion",
|
|
14
|
+
emojiPeople: "People & body",
|
|
15
|
+
emojiAnimals: "Animals & nature",
|
|
16
|
+
emojiFood: "Food & drink",
|
|
17
|
+
emojiTravel: "Travel & places",
|
|
18
|
+
emojiActivities: "Activities",
|
|
19
|
+
emojiObjects: "Objects",
|
|
20
|
+
emojiSymbols: "Symbols",
|
|
21
|
+
emojiFlags: "Flags",
|
|
22
|
+
emojiSkinTone: "Skin tone",
|
|
23
|
+
emojiToneDefault: "Default",
|
|
24
|
+
emojiToneLight: "Light",
|
|
25
|
+
emojiToneMediumLight: "Medium-light",
|
|
26
|
+
emojiToneMedium: "Medium",
|
|
27
|
+
emojiToneMediumDark: "Medium-dark",
|
|
28
|
+
emojiToneDark: "Dark",
|
|
29
|
+
emojiNoResults: "No emoji found",
|
|
30
|
+
emojiLoadFailed: "Emoji could not be loaded."
|
|
31
|
+
},
|
|
32
|
+
de: {
|
|
33
|
+
emojiPicker: "Emoji",
|
|
34
|
+
emojiSearch: "Emoji suchen",
|
|
35
|
+
emojiGroups: "Emoji-Gruppen",
|
|
36
|
+
emojiRecent: "Zuletzt verwendet",
|
|
37
|
+
emojiSmileys: "Smileys & Emotionen",
|
|
38
|
+
emojiPeople: "Menschen & Körper",
|
|
39
|
+
emojiAnimals: "Tiere & Natur",
|
|
40
|
+
emojiFood: "Essen & Trinken",
|
|
41
|
+
emojiTravel: "Reisen & Orte",
|
|
42
|
+
emojiActivities: "Aktivitäten",
|
|
43
|
+
emojiObjects: "Gegenstände",
|
|
44
|
+
emojiSymbols: "Symbole",
|
|
45
|
+
emojiFlags: "Flaggen",
|
|
46
|
+
emojiSkinTone: "Hautfarbe",
|
|
47
|
+
emojiToneDefault: "Standard",
|
|
48
|
+
emojiToneLight: "Hell",
|
|
49
|
+
emojiToneMediumLight: "Mittelhell",
|
|
50
|
+
emojiToneMedium: "Mittel",
|
|
51
|
+
emojiToneMediumDark: "Mitteldunkel",
|
|
52
|
+
emojiToneDark: "Dunkel",
|
|
53
|
+
emojiNoResults: "Kein Emoji gefunden",
|
|
54
|
+
emojiLoadFailed: "Emoji konnten nicht geladen werden."
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
/** Resolved from the inherited render locale, like the rest of @k2b/ui. */
|
|
59
|
+
export const useEmojiMessages = () => {
|
|
60
|
+
const locale = useLocale();
|
|
61
|
+
return () => emojiMessages.resolve([locale()]).t;
|
|
62
|
+
};
|
|
63
|
+
export const checkEmojiMessages = () => emojiMessages.check();
|
|
64
|
+
//# sourceMappingURL=emoji-messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/emoji/emoji-messages.ts"],"sourcesContent":["import { i18n } from \"@k2b/stdlib\";\nimport { useLocale } from \"../../intl/locale\";\n\n/** The picker's own strings. They live with the picker, so pages without it do not carry them. */\nconst emojiMessages = i18n.define({\n baseLocale: \"en\",\n messages: {\n en: {\n emojiPicker: \"Emoji\",\n emojiSearch: \"Search emoji\",\n emojiGroups: \"Emoji groups\",\n emojiRecent: \"Recently used\",\n emojiSmileys: \"Smileys & emotion\",\n emojiPeople: \"People & body\",\n emojiAnimals: \"Animals & nature\",\n emojiFood: \"Food & drink\",\n emojiTravel: \"Travel & places\",\n emojiActivities: \"Activities\",\n emojiObjects: \"Objects\",\n emojiSymbols: \"Symbols\",\n emojiFlags: \"Flags\",\n emojiSkinTone: \"Skin tone\",\n emojiToneDefault: \"Default\",\n emojiToneLight: \"Light\",\n emojiToneMediumLight: \"Medium-light\",\n emojiToneMedium: \"Medium\",\n emojiToneMediumDark: \"Medium-dark\",\n emojiToneDark: \"Dark\",\n emojiNoResults: \"No emoji found\",\n emojiLoadFailed: \"Emoji could not be loaded.\",\n },\n de: {\n emojiPicker: \"Emoji\",\n emojiSearch: \"Emoji suchen\",\n emojiGroups: \"Emoji-Gruppen\",\n emojiRecent: \"Zuletzt verwendet\",\n emojiSmileys: \"Smileys & Emotionen\",\n emojiPeople: \"Menschen & Körper\",\n emojiAnimals: \"Tiere & Natur\",\n emojiFood: \"Essen & Trinken\",\n emojiTravel: \"Reisen & Orte\",\n emojiActivities: \"Aktivitäten\",\n emojiObjects: \"Gegenstände\",\n emojiSymbols: \"Symbole\",\n emojiFlags: \"Flaggen\",\n emojiSkinTone: \"Hautfarbe\",\n emojiToneDefault: \"Standard\",\n emojiToneLight: \"Hell\",\n emojiToneMediumLight: \"Mittelhell\",\n emojiToneMedium: \"Mittel\",\n emojiToneMediumDark: \"Mitteldunkel\",\n emojiToneDark: \"Dunkel\",\n emojiNoResults: \"Kein Emoji gefunden\",\n emojiLoadFailed: \"Emoji konnten nicht geladen werden.\",\n },\n },\n});\n\nexport type EmojiMessages = ReturnType<(typeof emojiMessages)[\"resolve\"]>[\"t\"];\n\n/** Resolved from the inherited render locale, like the rest of @k2b/ui. */\nexport const useEmojiMessages = (): (() => EmojiMessages) => {\n const locale = useLocale();\n return () => emojiMessages.resolve([locale()]).t;\n};\n\nexport const checkEmojiMessages = () => emojiMessages.check();\n"],"mappings":"AAAA,SAAS,IAAI,QAAQ,aAAa;AAClC,SAAS,SAAS,QAAQ,mBAAmB;;AAE7C;AACA,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;EAChC,UAAU,EAAE,IAAI;EAChB,QAAQ,EAAE;IACR,EAAE,EAAE;MACF,WAAW,EAAE,OAAO;MACpB,WAAW,EAAE,cAAc;MAC3B,WAAW,EAAE,cAAc;MAC3B,WAAW,EAAE,eAAe;MAC5B,YAAY,EAAE,mBAAmB;MACjC,WAAW,EAAE,eAAe;MAC5B,YAAY,EAAE,kBAAkB;MAChC,SAAS,EAAE,cAAc;MACzB,WAAW,EAAE,iBAAiB;MAC9B,eAAe,EAAE,YAAY;MAC7B,YAAY,EAAE,SAAS;MACvB,YAAY,EAAE,SAAS;MACvB,UAAU,EAAE,OAAO;MACnB,aAAa,EAAE,WAAW;MAC1B,gBAAgB,EAAE,SAAS;MAC3B,cAAc,EAAE,OAAO;MACvB,oBAAoB,EAAE,cAAc;MACpC,eAAe,EAAE,QAAQ;MACzB,mBAAmB,EAAE,aAAa;MAClC,aAAa,EAAE,MAAM;MACrB,cAAc,EAAE,gBAAgB;MAChC,eAAe,EAAE;IACnB,CAAC;IACD,EAAE,EAAE;MACF,WAAW,EAAE,OAAO;MACpB,WAAW,EAAE,cAAc;MAC3B,WAAW,EAAE,eAAe;MAC5B,WAAW,EAAE,mBAAmB;MAChC,YAAY,EAAE,qBAAqB;MACnC,WAAW,EAAE,mBAAmB;MAChC,YAAY,EAAE,eAAe;MAC7B,SAAS,EAAE,iBAAiB;MAC5B,WAAW,EAAE,eAAe;MAC5B,eAAe,EAAE,aAAa;MAC9B,YAAY,EAAE,aAAa;MAC3B,YAAY,EAAE,SAAS;MACvB,UAAU,EAAE,SAAS;MACrB,aAAa,EAAE,WAAW;MAC1B,gBAAgB,EAAE,UAAU;MAC5B,cAAc,EAAE,MAAM;MACtB,oBAAoB,EAAE,YAAY;MAClC,eAAe,EAAE,QAAQ;MACzB,mBAAmB,EAAE,cAAc;MACnC,aAAa,EAAE,QAAQ;MACvB,cAAc,EAAE,qBAAqB;MACrC,eAAe,EAAE;IACnB;EACF;AACF,CAAC,CAAC;AAIF;AACA,OAAO,MAAM,gBAAgB,GAAG,MAA6B;EAC3D,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;EAC1B,OAAO,MAAM,aAAa,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,OAAO,MAAM,kBAAkB,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC","ignoreList":[]}
|
package/dist/ssr/inputs/index.js
CHANGED
|
@@ -2,10 +2,13 @@ export { AutocompleteEditor } from "./AutocompleteEditor";
|
|
|
2
2
|
export { AutocompleteSelect } from "./AutocompleteSelect";
|
|
3
3
|
export { Checkbox } from "./Checkbox";
|
|
4
4
|
export { CheckboxCard } from "./CheckboxCard";
|
|
5
|
+
export { ChoiceChips } from "./ChoiceChips";
|
|
5
6
|
export { ColorInput, PinInput, Slider } from "./ChoiceInputs";
|
|
6
7
|
export { Combobox } from "./Combobox";
|
|
7
8
|
export { abbreviations } from "./completion";
|
|
8
9
|
export { DatePicker, DateRangePicker, DateTimePicker } from "./DatePicker";
|
|
10
|
+
export { EmojiPicker } from "./emoji/EmojiPicker";
|
|
11
|
+
export { rememberEmoji } from "./emoji/emoji-index";
|
|
9
12
|
export { FileDropTarget, fileDropTarget } from "./FileDropTarget";
|
|
10
13
|
export { FileDropzone, ImageCropper, ImageInput } from "./FileInputs";
|
|
11
14
|
export { DEFAULT_ICON_GROUPS, DEFAULT_ICON_OPTIONS } from "./icon-options";
|
|
@@ -16,8 +19,10 @@ export { NumberInput } from "./NumberInput";
|
|
|
16
19
|
export { QrScanner } from "./QrScanner";
|
|
17
20
|
export { Select } from "./Select";
|
|
18
21
|
export { SelectChip } from "./SelectChip";
|
|
22
|
+
export { SignatureInput } from "./SignatureInput";
|
|
19
23
|
export { IconInput } from "./SpecialInputs";
|
|
20
24
|
export { Switch } from "./Switch";
|
|
25
|
+
export { parseSignature, signatureToPng } from "./signature";
|
|
21
26
|
export { TagEditor } from "./TagEditor";
|
|
22
27
|
export { TagsInput } from "./TagsInput";
|
|
23
28
|
export { createTemplateEditorPanesLayout, TemplateEditor, TemplatePreview, TemplateSampleData } from "./TemplateEditor";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/index.ts"],"sourcesContent":["export type { AutocompleteEditorProps } from \"./AutocompleteEditor\";\nexport { AutocompleteEditor } from \"./AutocompleteEditor\";\nexport type {\n AutocompleteSelectOption,\n AutocompleteSelectProps,\n AutocompleteSelectSearchResult,\n} from \"./AutocompleteSelect\";\nexport { AutocompleteSelect } from \"./AutocompleteSelect\";\nexport type { CheckboxProps } from \"./Checkbox\";\nexport { Checkbox } from \"./Checkbox\";\nexport type { CheckboxCardProps } from \"./CheckboxCard\";\nexport { CheckboxCard } from \"./CheckboxCard\";\nexport type {\n ColorInputProps,\n PinInputProps,\n SliderProps,\n} from \"./ChoiceInputs\";\nexport { ColorInput, PinInput, Slider } from \"./ChoiceInputs\";\nexport type { ComboboxOption, ComboboxProps } from \"./Combobox\";\nexport { Combobox } from \"./Combobox\";\nexport type { ChoiceOption, ChoiceOptionsLoader } from \"./choice\";\nexport type {\n Completion,\n QueryContext,\n SuggestContext,\n Suggestion,\n} from \"./completion\";\nexport { abbreviations } from \"./completion\";\nexport type {\n DatePickerBaseProps,\n DatePickerProps,\n DatePreset,\n DateRangePickerProps,\n DateRangeValue,\n DateTimePickerProps,\n DurationPreset,\n} from \"./DatePicker\";\nexport { DatePicker, DateRangePicker, DateTimePicker } from \"./DatePicker\";\nexport type { FileDropDetails, FileDropOptions, FileDropRejection, FileDropTargetProps } from \"./FileDropTarget\";\nexport { FileDropTarget, fileDropTarget } from \"./FileDropTarget\";\nexport type { FileDropzoneProps, ImageCropperProps, ImageInputProps } from \"./FileInputs\";\nexport { FileDropzone, ImageCropper, ImageInput } from \"./FileInputs\";\nexport type { DateContext, FieldProps, MaybeAccessor, ValueFieldProps } from \"./field-contract\";\nexport { DEFAULT_ICON_GROUPS, DEFAULT_ICON_OPTIONS } from \"./icon-options\";\nexport type {\n ImageCropAspect,\n ImageCropOutput,\n ImageCropRect,\n ImageCropRotation,\n ImageCropSize,\n ImageCropSource,\n ImageCropState,\n} from \"./image-crop\";\nexport {\n clampImageCropRect,\n createCroppedImageCanvas,\n createCroppedImageDataUrl,\n getInitialImageCropRect,\n imageCropRectToPixels,\n normalizeImageCropRotation,\n resizeImageCropAroundCenter,\n rotateImageCropRight,\n} from \"./image-crop\";\nexport type {\n MultiSelectFetchDataFn,\n MultiSelectInputProps,\n MultiSelectOption,\n} from \"./MultiSelectInput\";\nexport { MultiSelectInput } from \"./MultiSelectInput\";\nexport type { MarkdownEditorProps } from \"./markdown/MarkdownEditor\";\nexport { MarkdownEditor } from \"./markdown/MarkdownEditor\";\nexport type { NumberInputProps } from \"./NumberInput\";\nexport { NumberInput } from \"./NumberInput\";\nexport type { QrScannerError, QrScannerProps } from \"./QrScanner\";\nexport { QrScanner } from \"./QrScanner\";\nexport type { ChoiceAppearance, SelectGridSize, SelectGroup, SelectOption, SelectProps, SelectSourceOption, SelectView } from \"./Select\";\nexport { Select } from \"./Select\";\nexport type { SelectChipOption, SelectChipProps } from \"./SelectChip\";\nexport { SelectChip } from \"./SelectChip\";\nexport type { IconInputProps, IconOption } from \"./SpecialInputs\";\nexport { IconInput } from \"./SpecialInputs\";\nexport type { SwitchProps } from \"./Switch\";\nexport { Switch } from \"./Switch\";\nexport type { TagEditorItem, TagEditorLabels, TagEditorProps, TagEditorValue } from \"./TagEditor\";\nexport { TagEditor } from \"./TagEditor\";\nexport type { TagsInputProps } from \"./TagsInput\";\nexport { TagsInput } from \"./TagsInput\";\nexport type {\n TemplateEditorLayout,\n TemplateEditorProps,\n TemplatePreviewProps,\n TemplateSampleDataProps,\n TemplateVariable,\n TemplateVariableKind,\n} from \"./TemplateEditor\";\nexport {\n createTemplateEditorPanesLayout,\n TemplateEditor,\n TemplatePreview,\n TemplateSampleData,\n} from \"./TemplateEditor\";\nexport type { TextInputProps } from \"./TextInput\";\nexport { TextInput } from \"./TextInput\";\n"],"mappings":"AACA,SAAS,kBAAkB,QAAQ,sBAAsB;AAMzD,SAAS,kBAAkB,QAAQ,sBAAsB;AAEzD,SAAS,QAAQ,QAAQ,YAAY;AAErC,SAAS,YAAY,QAAQ,gBAAgB;
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/index.ts"],"sourcesContent":["export type { AutocompleteEditorProps } from \"./AutocompleteEditor\";\nexport { AutocompleteEditor } from \"./AutocompleteEditor\";\nexport type {\n AutocompleteSelectOption,\n AutocompleteSelectProps,\n AutocompleteSelectSearchResult,\n} from \"./AutocompleteSelect\";\nexport { AutocompleteSelect } from \"./AutocompleteSelect\";\nexport type { CheckboxProps } from \"./Checkbox\";\nexport { Checkbox } from \"./Checkbox\";\nexport type { CheckboxCardProps } from \"./CheckboxCard\";\nexport { CheckboxCard } from \"./CheckboxCard\";\nexport type { ChoiceChipOption, ChoiceChipsProps } from \"./ChoiceChips\";\nexport { ChoiceChips } from \"./ChoiceChips\";\nexport type {\n ColorInputProps,\n PinInputProps,\n SliderProps,\n} from \"./ChoiceInputs\";\nexport { ColorInput, PinInput, Slider } from \"./ChoiceInputs\";\nexport type { ComboboxOption, ComboboxProps } from \"./Combobox\";\nexport { Combobox } from \"./Combobox\";\nexport type { ChoiceOption, ChoiceOptionsLoader } from \"./choice\";\nexport type {\n Completion,\n QueryContext,\n SuggestContext,\n Suggestion,\n} from \"./completion\";\nexport { abbreviations } from \"./completion\";\nexport type {\n DatePickerBaseProps,\n DatePickerProps,\n DatePreset,\n DateRangePickerProps,\n DateRangeValue,\n DateTimePickerProps,\n DurationPreset,\n} from \"./DatePicker\";\nexport { DatePicker, DateRangePicker, DateTimePicker } from \"./DatePicker\";\nexport type { EmojiPickerPopoverProps, EmojiPickerProps } from \"./emoji/EmojiPicker\";\nexport { EmojiPicker } from \"./emoji/EmojiPicker\";\nexport type { EmojiSkinTone } from \"./emoji/emoji-index\";\nexport { rememberEmoji } from \"./emoji/emoji-index\";\nexport type { FileDropDetails, FileDropOptions, FileDropRejection, FileDropTargetProps } from \"./FileDropTarget\";\nexport { FileDropTarget, fileDropTarget } from \"./FileDropTarget\";\nexport type { FileDropzoneProps, ImageCropperProps, ImageInputProps } from \"./FileInputs\";\nexport { FileDropzone, ImageCropper, ImageInput } from \"./FileInputs\";\nexport type { DateContext, FieldProps, MaybeAccessor, ValueFieldProps } from \"./field-contract\";\nexport { DEFAULT_ICON_GROUPS, DEFAULT_ICON_OPTIONS } from \"./icon-options\";\nexport type {\n ImageCropAspect,\n ImageCropOutput,\n ImageCropRect,\n ImageCropRotation,\n ImageCropSize,\n ImageCropSource,\n ImageCropState,\n} from \"./image-crop\";\nexport {\n clampImageCropRect,\n createCroppedImageCanvas,\n createCroppedImageDataUrl,\n getInitialImageCropRect,\n imageCropRectToPixels,\n normalizeImageCropRotation,\n resizeImageCropAroundCenter,\n rotateImageCropRight,\n} from \"./image-crop\";\nexport type {\n MultiSelectFetchDataFn,\n MultiSelectInputProps,\n MultiSelectOption,\n} from \"./MultiSelectInput\";\nexport { MultiSelectInput } from \"./MultiSelectInput\";\nexport type { MarkdownEditorProps } from \"./markdown/MarkdownEditor\";\nexport { MarkdownEditor } from \"./markdown/MarkdownEditor\";\nexport type { NumberInputProps } from \"./NumberInput\";\nexport { NumberInput } from \"./NumberInput\";\nexport type { QrScannerError, QrScannerProps } from \"./QrScanner\";\nexport { QrScanner } from \"./QrScanner\";\nexport type { ChoiceAppearance, SelectGridSize, SelectGroup, SelectOption, SelectProps, SelectSourceOption, SelectView } from \"./Select\";\nexport { Select } from \"./Select\";\nexport type { SelectChipOption, SelectChipProps } from \"./SelectChip\";\nexport { SelectChip } from \"./SelectChip\";\nexport type { SignatureInputProps } from \"./SignatureInput\";\nexport { SignatureInput } from \"./SignatureInput\";\nexport type { IconInputProps, IconOption } from \"./SpecialInputs\";\nexport { IconInput } from \"./SpecialInputs\";\nexport type { SwitchProps } from \"./Switch\";\nexport { Switch } from \"./Switch\";\nexport type { SignaturePngOptions, SignatureValue } from \"./signature\";\nexport { parseSignature, signatureToPng } from \"./signature\";\nexport type { TagEditorItem, TagEditorLabels, TagEditorProps, TagEditorValue } from \"./TagEditor\";\nexport { TagEditor } from \"./TagEditor\";\nexport type { TagsInputProps } from \"./TagsInput\";\nexport { TagsInput } from \"./TagsInput\";\nexport type {\n TemplateEditorLayout,\n TemplateEditorProps,\n TemplatePreviewProps,\n TemplateSampleDataProps,\n TemplateVariable,\n TemplateVariableKind,\n} from \"./TemplateEditor\";\nexport {\n createTemplateEditorPanesLayout,\n TemplateEditor,\n TemplatePreview,\n TemplateSampleData,\n} from \"./TemplateEditor\";\nexport type { TextInputProps } from \"./TextInput\";\nexport { TextInput } from \"./TextInput\";\n"],"mappings":"AACA,SAAS,kBAAkB,QAAQ,sBAAsB;AAMzD,SAAS,kBAAkB,QAAQ,sBAAsB;AAEzD,SAAS,QAAQ,QAAQ,YAAY;AAErC,SAAS,YAAY,QAAQ,gBAAgB;AAE7C,SAAS,WAAW,QAAQ,eAAe;AAM3C,SAAS,UAAU,EAAE,QAAQ,EAAE,MAAM,QAAQ,gBAAgB;AAE7D,SAAS,QAAQ,QAAQ,YAAY;AAQrC,SAAS,aAAa,QAAQ,cAAc;AAU5C,SAAS,UAAU,EAAE,eAAe,EAAE,cAAc,QAAQ,cAAc;AAE1E,SAAS,WAAW,QAAQ,qBAAqB;AAEjD,SAAS,aAAa,QAAQ,qBAAqB;AAEnD,SAAS,cAAc,EAAE,cAAc,QAAQ,kBAAkB;AAEjE,SAAS,YAAY,EAAE,YAAY,EAAE,UAAU,QAAQ,cAAc;AAErE,SAAS,mBAAmB,EAAE,oBAAoB,QAAQ,gBAAgB;AAU1E,SACE,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,oBAAoB,QACf,cAAc;AAMrB,SAAS,gBAAgB,QAAQ,oBAAoB;AAErD,SAAS,cAAc,QAAQ,2BAA2B;AAE1D,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,SAAS,QAAQ,aAAa;AAEvC,SAAS,MAAM,QAAQ,UAAU;AAEjC,SAAS,UAAU,QAAQ,cAAc;AAEzC,SAAS,cAAc,QAAQ,kBAAkB;AAEjD,SAAS,SAAS,QAAQ,iBAAiB;AAE3C,SAAS,MAAM,QAAQ,UAAU;AAEjC,SAAS,cAAc,EAAE,cAAc,QAAQ,aAAa;AAE5D,SAAS,SAAS,QAAQ,aAAa;AAEvC,SAAS,SAAS,QAAQ,aAAa;AASvC,SACE,+BAA+B,EAC/B,cAAc,EACd,eAAe,EACf,kBAAkB,QACb,kBAAkB;AAEzB,SAAS,SAAS,QAAQ,aAAa","ignoreList":[]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { replaceTextareaRange as replaceRange } from "../editor-dom";
|
|
2
|
+
import { closesCodeFence, openCodeFence } from "./code-zone";
|
|
2
3
|
const lineAt = (value, position) => {
|
|
3
4
|
const lineStart = value.lastIndexOf("\n", position - 1) + 1;
|
|
4
5
|
const nextNewline = value.indexOf("\n", position);
|
|
@@ -31,15 +32,17 @@ const toggleInlineWrap = (textarea, marker, placeholder) => {
|
|
|
31
32
|
selectionEnd
|
|
32
33
|
} = textarea;
|
|
33
34
|
const markerLength = marker.length;
|
|
35
|
+
// A one-character marker never takes half of a doubled one, so italic `*` leaves bold `**` alone.
|
|
36
|
+
const doubled = (text, from, step) => markerLength === 1 && text[from] === marker && text[from + step] === marker && text[from + 2 * step] !== marker;
|
|
34
37
|
const before = value.slice(Math.max(0, selectionStart - markerLength), selectionStart);
|
|
35
38
|
const after = value.slice(selectionEnd, selectionEnd + markerLength);
|
|
36
|
-
if (before === marker && after === marker) {
|
|
39
|
+
if (before === marker && after === marker && !doubled(value, selectionStart - 1, -1) && !doubled(value, selectionEnd, 1)) {
|
|
37
40
|
replaceRange(textarea, selectionStart - markerLength, selectionEnd + markerLength, value.slice(selectionStart, selectionEnd));
|
|
38
41
|
textarea.setSelectionRange(selectionStart - markerLength, selectionEnd - markerLength);
|
|
39
42
|
return;
|
|
40
43
|
}
|
|
41
44
|
const selected = value.slice(selectionStart, selectionEnd);
|
|
42
|
-
if (selected.length >= markerLength * 2 && selected.startsWith(marker) && selected.endsWith(marker)) {
|
|
45
|
+
if (selected.length >= markerLength * 2 && selected.startsWith(marker) && selected.endsWith(marker) && !doubled(selected, 0, 1) && !doubled(selected, selected.length - 1, -1)) {
|
|
43
46
|
const stripped = selected.slice(markerLength, -markerLength);
|
|
44
47
|
replaceRange(textarea, selectionStart, selectionEnd, stripped);
|
|
45
48
|
textarea.setSelectionRange(selectionStart, selectionStart + stripped.length);
|
|
@@ -56,6 +59,8 @@ const toggleInlineWrap = (textarea, marker, placeholder) => {
|
|
|
56
59
|
export const toggleBold = textarea => toggleInlineWrap(textarea, "**", "bold text");
|
|
57
60
|
export const toggleItalic = textarea => toggleInlineWrap(textarea, "*", "italic text");
|
|
58
61
|
export const toggleCode = textarea => toggleInlineWrap(textarea, "`", "code");
|
|
62
|
+
/** Wraps the selection in `marker`, or unwraps it; without a selection the caret lands between two markers. */
|
|
63
|
+
export const toggleInlineMarker = (textarea, marker) => toggleInlineWrap(textarea, marker, "");
|
|
59
64
|
export const insertLink = (textarea, url) => {
|
|
60
65
|
const {
|
|
61
66
|
value,
|
|
@@ -112,6 +117,47 @@ export const toggleHeading = (textarea, level) => {
|
|
|
112
117
|
textarea.setSelectionRange(caret, caret);
|
|
113
118
|
};
|
|
114
119
|
export const toggleBulletList = textarea => togglePrefix(textarea, "- ");
|
|
120
|
+
|
|
121
|
+
/** Puts the selected lines between ``` fences. Inside a fenced block, from its opening line on, it removes that block's fences. */
|
|
122
|
+
export const toggleCodeBlock = textarea => {
|
|
123
|
+
const {
|
|
124
|
+
value
|
|
125
|
+
} = textarea;
|
|
126
|
+
const {
|
|
127
|
+
start,
|
|
128
|
+
end,
|
|
129
|
+
lines
|
|
130
|
+
} = selectedLineRange(textarea);
|
|
131
|
+
const open = openCodeFence(value, lineAt(value, start).lineEnd);
|
|
132
|
+
if (open) {
|
|
133
|
+
const bodyStart = Math.min(lineAt(value, open.start).lineEnd + 1, value.length);
|
|
134
|
+
// An unclosed block runs to the end of the text.
|
|
135
|
+
let bodyEnd = value.length;
|
|
136
|
+
let blockEnd = value.length;
|
|
137
|
+
for (let lineStart = bodyStart; lineStart < value.length;) {
|
|
138
|
+
const {
|
|
139
|
+
lineEnd,
|
|
140
|
+
line
|
|
141
|
+
} = lineAt(value, lineStart);
|
|
142
|
+
if (closesCodeFence(line, open.marker)) {
|
|
143
|
+
bodyEnd = Math.max(bodyStart, lineStart - 1);
|
|
144
|
+
blockEnd = lineEnd;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
lineStart = lineEnd + 1;
|
|
148
|
+
}
|
|
149
|
+
const body = value.slice(bodyStart, bodyEnd);
|
|
150
|
+
replaceRange(textarea, open.start, blockEnd, body);
|
|
151
|
+
textarea.setSelectionRange(open.start, open.start + body.length);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const body = lines.join("\n");
|
|
155
|
+
// A fence in the selection would close a ``` block early, so the new block's fence is longer than any of them.
|
|
156
|
+
const longest = Math.max(0, ...lines.map(line => /^(?:[ \t]*>)*[ \t]*(`{3,})/.exec(line)?.[1].length ?? 0));
|
|
157
|
+
const fence = "`".repeat(Math.max(3, longest + 1));
|
|
158
|
+
replaceRange(textarea, start, end, `${fence}\n${body}\n${fence}`);
|
|
159
|
+
textarea.setSelectionRange(start + fence.length + 1, start + fence.length + 1 + body.length);
|
|
160
|
+
};
|
|
115
161
|
export const toggleQuote = textarea => togglePrefix(textarea, "> ");
|
|
116
162
|
export const toggleNumberedList = textarea => {
|
|
117
163
|
const {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/markdown/actions.ts"],"sourcesContent":["import { replaceTextareaRange as replaceRange } from \"../editor-dom\";\n\nconst lineAt = (value: string, position: number): { lineStart: number; lineEnd: number; line: string } => {\n const lineStart = value.lastIndexOf(\"\\n\", position - 1) + 1;\n const nextNewline = value.indexOf(\"\\n\", position);\n const lineEnd = nextNewline === -1 ? value.length : nextNewline;\n return { lineStart, lineEnd, line: value.slice(lineStart, lineEnd) };\n};\n\nconst selectedLineRange = (textarea: HTMLTextAreaElement): { start: number; end: number; lines: string[] } => {\n const { value, selectionStart, selectionEnd } = textarea;\n const startLine = lineAt(value, selectionStart);\n const adjustedEnd =\n selectionEnd > selectionStart && selectionEnd > 0 && value[selectionEnd - 1] === \"\\n\" ? selectionEnd - 1 : selectionEnd;\n const endLine = lineAt(value, adjustedEnd);\n return {\n start: startLine.lineStart,\n end: endLine.lineEnd,\n lines: value.slice(startLine.lineStart, endLine.lineEnd).split(\"\\n\"),\n };\n};\n\nconst toggleInlineWrap = (textarea: HTMLTextAreaElement, marker: string, placeholder: string): void => {\n const { value, selectionStart, selectionEnd } = textarea;\n const markerLength = marker.length;\n const before = value.slice(Math.max(0, selectionStart - markerLength), selectionStart);\n const after = value.slice(selectionEnd, selectionEnd + markerLength);\n if (before === marker && after === marker) {\n replaceRange(textarea, selectionStart - markerLength, selectionEnd + markerLength, value.slice(selectionStart, selectionEnd));\n textarea.setSelectionRange(selectionStart - markerLength, selectionEnd - markerLength);\n return;\n }\n\n const selected = value.slice(selectionStart, selectionEnd);\n if (selected.length >= markerLength * 2 && selected.startsWith(marker) && selected.endsWith(marker)) {\n const stripped = selected.slice(markerLength, -markerLength);\n replaceRange(textarea, selectionStart, selectionEnd, stripped);\n textarea.setSelectionRange(selectionStart, selectionStart + stripped.length);\n return;\n }\n\n if (selectionStart === selectionEnd) {\n replaceRange(textarea, selectionStart, selectionEnd, marker + placeholder + marker);\n textarea.setSelectionRange(selectionStart + markerLength, selectionStart + markerLength + placeholder.length);\n } else {\n replaceRange(textarea, selectionStart, selectionEnd, marker + selected + marker);\n textarea.setSelectionRange(selectionStart + markerLength, selectionStart + markerLength + selected.length);\n }\n};\n\nexport const toggleBold = (textarea: HTMLTextAreaElement): void => toggleInlineWrap(textarea, \"**\", \"bold text\");\nexport const toggleItalic = (textarea: HTMLTextAreaElement): void => toggleInlineWrap(textarea, \"*\", \"italic text\");\nexport const toggleCode = (textarea: HTMLTextAreaElement): void => toggleInlineWrap(textarea, \"`\", \"code\");\n\nexport const insertLink = (textarea: HTMLTextAreaElement, url?: string): void => {\n const { value, selectionStart, selectionEnd } = textarea;\n const selected = value.slice(selectionStart, selectionEnd);\n const label = selected || \"link\";\n const finalUrl = url ?? \"\";\n replaceRange(textarea, selectionStart, selectionEnd, `[${label}](${finalUrl})`);\n if (finalUrl) {\n textarea.setSelectionRange(selectionStart + 1, selectionStart + 1 + label.length);\n } else {\n const caret = selectionStart + label.length + 3;\n textarea.setSelectionRange(caret, caret);\n }\n};\n\nconst togglePrefix = (textarea: HTMLTextAreaElement, prefix: string): void => {\n const { start, end, lines } = selectedLineRange(textarea);\n const parts = lines.map((line) => {\n const match = /^(\\s*)(.*)$/.exec(line)!;\n return { indent: match[1]!, body: match[2]! };\n });\n const remove = parts.every(({ body }) => body.startsWith(prefix));\n const replacement = parts.map(({ indent, body }) => (remove ? indent + body.slice(prefix.length) : indent + prefix + body)).join(\"\\n\");\n replaceRange(textarea, start, end, replacement);\n textarea.setSelectionRange(start, start + replacement.length);\n};\n\nexport const toggleHeading = (textarea: HTMLTextAreaElement, level: 1 | 2 | 3): void => {\n const oldCaret = textarea.selectionStart;\n const { lineStart, lineEnd, line } = lineAt(textarea.value, oldCaret);\n const prefix = `${\"#\".repeat(level)} `;\n const existing = /^(#{1,6})\\s/.exec(line);\n const next =\n existing?.[1]?.length === level ? line.slice(existing[0].length) : existing ? prefix + line.slice(existing[0].length) : prefix + line;\n replaceRange(textarea, lineStart, lineEnd, next);\n const desired = Math.max(lineStart, oldCaret + next.length - line.length);\n const caret = Math.min(desired, lineStart + next.length);\n textarea.setSelectionRange(caret, caret);\n};\n\nexport const toggleBulletList = (textarea: HTMLTextAreaElement): void => togglePrefix(textarea, \"- \");\nexport const toggleQuote = (textarea: HTMLTextAreaElement): void => togglePrefix(textarea, \"> \");\n\nexport const toggleNumberedList = (textarea: HTMLTextAreaElement): void => {\n const { start, end, lines } = selectedLineRange(textarea);\n const parts = lines.map((line) => {\n const match = /^(\\s*)(\\d+\\.\\s)?(.*)$/.exec(line)!;\n return {\n indent: match[1] ?? \"\",\n marker: match[2],\n body: match[3] ?? \"\",\n };\n });\n const remove = parts.every(({ marker }) => Boolean(marker));\n const replacement = parts.map(({ indent, body }, index) => (remove ? indent + body : `${indent}${index + 1}. ${body}`)).join(\"\\n\");\n replaceRange(textarea, start, end, replacement);\n textarea.setSelectionRange(start, start + replacement.length);\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/markdown/actions.ts"],"sourcesContent":["import { replaceTextareaRange as replaceRange } from \"../editor-dom\";\nimport { closesCodeFence, openCodeFence } from \"./code-zone\";\n\nconst lineAt = (value: string, position: number): { lineStart: number; lineEnd: number; line: string } => {\n const lineStart = value.lastIndexOf(\"\\n\", position - 1) + 1;\n const nextNewline = value.indexOf(\"\\n\", position);\n const lineEnd = nextNewline === -1 ? value.length : nextNewline;\n return { lineStart, lineEnd, line: value.slice(lineStart, lineEnd) };\n};\n\nconst selectedLineRange = (textarea: HTMLTextAreaElement): { start: number; end: number; lines: string[] } => {\n const { value, selectionStart, selectionEnd } = textarea;\n const startLine = lineAt(value, selectionStart);\n const adjustedEnd =\n selectionEnd > selectionStart && selectionEnd > 0 && value[selectionEnd - 1] === \"\\n\" ? selectionEnd - 1 : selectionEnd;\n const endLine = lineAt(value, adjustedEnd);\n return {\n start: startLine.lineStart,\n end: endLine.lineEnd,\n lines: value.slice(startLine.lineStart, endLine.lineEnd).split(\"\\n\"),\n };\n};\n\nconst toggleInlineWrap = (textarea: HTMLTextAreaElement, marker: string, placeholder: string): void => {\n const { value, selectionStart, selectionEnd } = textarea;\n const markerLength = marker.length;\n // A one-character marker never takes half of a doubled one, so italic `*` leaves bold `**` alone.\n const doubled = (text: string, from: number, step: 1 | -1) =>\n markerLength === 1 && text[from] === marker && text[from + step] === marker && text[from + 2 * step] !== marker;\n const before = value.slice(Math.max(0, selectionStart - markerLength), selectionStart);\n const after = value.slice(selectionEnd, selectionEnd + markerLength);\n if (before === marker && after === marker && !doubled(value, selectionStart - 1, -1) && !doubled(value, selectionEnd, 1)) {\n replaceRange(textarea, selectionStart - markerLength, selectionEnd + markerLength, value.slice(selectionStart, selectionEnd));\n textarea.setSelectionRange(selectionStart - markerLength, selectionEnd - markerLength);\n return;\n }\n\n const selected = value.slice(selectionStart, selectionEnd);\n if (\n selected.length >= markerLength * 2 &&\n selected.startsWith(marker) &&\n selected.endsWith(marker) &&\n !doubled(selected, 0, 1) &&\n !doubled(selected, selected.length - 1, -1)\n ) {\n const stripped = selected.slice(markerLength, -markerLength);\n replaceRange(textarea, selectionStart, selectionEnd, stripped);\n textarea.setSelectionRange(selectionStart, selectionStart + stripped.length);\n return;\n }\n\n if (selectionStart === selectionEnd) {\n replaceRange(textarea, selectionStart, selectionEnd, marker + placeholder + marker);\n textarea.setSelectionRange(selectionStart + markerLength, selectionStart + markerLength + placeholder.length);\n } else {\n replaceRange(textarea, selectionStart, selectionEnd, marker + selected + marker);\n textarea.setSelectionRange(selectionStart + markerLength, selectionStart + markerLength + selected.length);\n }\n};\n\nexport const toggleBold = (textarea: HTMLTextAreaElement): void => toggleInlineWrap(textarea, \"**\", \"bold text\");\nexport const toggleItalic = (textarea: HTMLTextAreaElement): void => toggleInlineWrap(textarea, \"*\", \"italic text\");\nexport const toggleCode = (textarea: HTMLTextAreaElement): void => toggleInlineWrap(textarea, \"`\", \"code\");\n/** Wraps the selection in `marker`, or unwraps it; without a selection the caret lands between two markers. */\nexport const toggleInlineMarker = (textarea: HTMLTextAreaElement, marker: string): void => toggleInlineWrap(textarea, marker, \"\");\n\nexport const insertLink = (textarea: HTMLTextAreaElement, url?: string): void => {\n const { value, selectionStart, selectionEnd } = textarea;\n const selected = value.slice(selectionStart, selectionEnd);\n const label = selected || \"link\";\n const finalUrl = url ?? \"\";\n replaceRange(textarea, selectionStart, selectionEnd, `[${label}](${finalUrl})`);\n if (finalUrl) {\n textarea.setSelectionRange(selectionStart + 1, selectionStart + 1 + label.length);\n } else {\n const caret = selectionStart + label.length + 3;\n textarea.setSelectionRange(caret, caret);\n }\n};\n\nconst togglePrefix = (textarea: HTMLTextAreaElement, prefix: string): void => {\n const { start, end, lines } = selectedLineRange(textarea);\n const parts = lines.map((line) => {\n const match = /^(\\s*)(.*)$/.exec(line)!;\n return { indent: match[1]!, body: match[2]! };\n });\n const remove = parts.every(({ body }) => body.startsWith(prefix));\n const replacement = parts.map(({ indent, body }) => (remove ? indent + body.slice(prefix.length) : indent + prefix + body)).join(\"\\n\");\n replaceRange(textarea, start, end, replacement);\n textarea.setSelectionRange(start, start + replacement.length);\n};\n\nexport const toggleHeading = (textarea: HTMLTextAreaElement, level: 1 | 2 | 3): void => {\n const oldCaret = textarea.selectionStart;\n const { lineStart, lineEnd, line } = lineAt(textarea.value, oldCaret);\n const prefix = `${\"#\".repeat(level)} `;\n const existing = /^(#{1,6})\\s/.exec(line);\n const next =\n existing?.[1]?.length === level ? line.slice(existing[0].length) : existing ? prefix + line.slice(existing[0].length) : prefix + line;\n replaceRange(textarea, lineStart, lineEnd, next);\n const desired = Math.max(lineStart, oldCaret + next.length - line.length);\n const caret = Math.min(desired, lineStart + next.length);\n textarea.setSelectionRange(caret, caret);\n};\n\nexport const toggleBulletList = (textarea: HTMLTextAreaElement): void => togglePrefix(textarea, \"- \");\n\n/** Puts the selected lines between ``` fences. Inside a fenced block, from its opening line on, it removes that block's fences. */\nexport const toggleCodeBlock = (textarea: HTMLTextAreaElement): void => {\n const { value } = textarea;\n const { start, end, lines } = selectedLineRange(textarea);\n const open = openCodeFence(value, lineAt(value, start).lineEnd);\n if (open) {\n const bodyStart = Math.min(lineAt(value, open.start).lineEnd + 1, value.length);\n // An unclosed block runs to the end of the text.\n let bodyEnd = value.length;\n let blockEnd = value.length;\n for (let lineStart = bodyStart; lineStart < value.length; ) {\n const { lineEnd, line } = lineAt(value, lineStart);\n if (closesCodeFence(line, open.marker)) {\n bodyEnd = Math.max(bodyStart, lineStart - 1);\n blockEnd = lineEnd;\n break;\n }\n lineStart = lineEnd + 1;\n }\n const body = value.slice(bodyStart, bodyEnd);\n replaceRange(textarea, open.start, blockEnd, body);\n textarea.setSelectionRange(open.start, open.start + body.length);\n return;\n }\n const body = lines.join(\"\\n\");\n // A fence in the selection would close a ``` block early, so the new block's fence is longer than any of them.\n const longest = Math.max(0, ...lines.map((line) => /^(?:[ \\t]*>)*[ \\t]*(`{3,})/.exec(line)?.[1]!.length ?? 0));\n const fence = \"`\".repeat(Math.max(3, longest + 1));\n replaceRange(textarea, start, end, `${fence}\\n${body}\\n${fence}`);\n textarea.setSelectionRange(start + fence.length + 1, start + fence.length + 1 + body.length);\n};\n\nexport const toggleQuote = (textarea: HTMLTextAreaElement): void => togglePrefix(textarea, \"> \");\n\nexport const toggleNumberedList = (textarea: HTMLTextAreaElement): void => {\n const { start, end, lines } = selectedLineRange(textarea);\n const parts = lines.map((line) => {\n const match = /^(\\s*)(\\d+\\.\\s)?(.*)$/.exec(line)!;\n return {\n indent: match[1] ?? \"\",\n marker: match[2],\n body: match[3] ?? \"\",\n };\n });\n const remove = parts.every(({ marker }) => Boolean(marker));\n const replacement = parts.map(({ indent, body }, index) => (remove ? indent + body : `${indent}${index + 1}. ${body}`)).join(\"\\n\");\n replaceRange(textarea, start, end, replacement);\n textarea.setSelectionRange(start, start + replacement.length);\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,7 +1,43 @@
|
|
|
1
|
+
/** A fence line: optional quote markers and indentation, then three or more backticks or tildes, then the rest. */
|
|
2
|
+
const fenceLine = /^(?:[ \t]*>)*[ \t]*(`{3,}|~{3,})(.*)$/;
|
|
3
|
+
|
|
4
|
+
/** Whether `line` closes a block that `marker` opened: the same character, at least as many, nothing after it. */
|
|
5
|
+
export const closesCodeFence = (line, marker) => {
|
|
6
|
+
const fence = fenceLine.exec(line);
|
|
7
|
+
return Boolean(fence && fence[1][0] === marker[0] && fence[1].length >= marker.length && !fence[2].trim());
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/** How many quotes `line` is in: the `>` markers before its content. */
|
|
11
|
+
const quoteDepth = line => (/^(?:[ \t]*>)*/.exec(line)[0].match(/>/g) ?? []).length;
|
|
12
|
+
|
|
13
|
+
/** The fenced code block that is still open at `position`, judged by the text before it: its opening line's start and marker. */
|
|
14
|
+
export const openCodeFence = (text, position) => {
|
|
15
|
+
let open = null;
|
|
16
|
+
let start = 0;
|
|
17
|
+
for (const line of text.slice(0, position).split("\n")) {
|
|
18
|
+
// A block inside a quote ends with that quote, for example at a blank line or an unquoted one.
|
|
19
|
+
if (open && quoteDepth(line) < open.depth) open = null;
|
|
20
|
+
if (open) {
|
|
21
|
+
if (closesCodeFence(line, open.marker)) open = null;
|
|
22
|
+
} else {
|
|
23
|
+
const fence = fenceLine.exec(line);
|
|
24
|
+
// A backtick in the info string makes the line inline code instead of a fence.
|
|
25
|
+
if (fence && !(fence[1][0] === "`" && fence[2].includes("`"))) open = {
|
|
26
|
+
start,
|
|
27
|
+
marker: fence[1],
|
|
28
|
+
depth: quoteDepth(line)
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
start += line.length + 1;
|
|
32
|
+
}
|
|
33
|
+
return open && {
|
|
34
|
+
start: open.start,
|
|
35
|
+
marker: open.marker
|
|
36
|
+
};
|
|
37
|
+
};
|
|
1
38
|
export const isInCodeZone = (text, position) => {
|
|
39
|
+
if (openCodeFence(text, position)) return true;
|
|
2
40
|
const before = text.slice(0, position);
|
|
3
|
-
const fences = before.match(/^```/gm);
|
|
4
|
-
if (fences && fences.length % 2 !== 0) return true;
|
|
5
41
|
const line = before.slice(before.lastIndexOf("\n") + 1);
|
|
6
42
|
return (line.match(/`/g) ?? []).length % 2 !== 0;
|
|
7
43
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["inputs/markdown/code-zone.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"names":[],"sources":["inputs/markdown/code-zone.ts"],"sourcesContent":["/** A fence line: optional quote markers and indentation, then three or more backticks or tildes, then the rest. */\nconst fenceLine = /^(?:[ \\t]*>)*[ \\t]*(`{3,}|~{3,})(.*)$/;\n\n/** Whether `line` closes a block that `marker` opened: the same character, at least as many, nothing after it. */\nexport const closesCodeFence = (line: string, marker: string): boolean => {\n const fence = fenceLine.exec(line);\n return Boolean(fence && fence[1]![0] === marker[0] && fence[1]!.length >= marker.length && !fence[2]!.trim());\n};\n\n/** How many quotes `line` is in: the `>` markers before its content. */\nconst quoteDepth = (line: string): number => (/^(?:[ \\t]*>)*/.exec(line)![0].match(/>/g) ?? []).length;\n\n/** The fenced code block that is still open at `position`, judged by the text before it: its opening line's start and marker. */\nexport const openCodeFence = (text: string, position: number): { start: number; marker: string } | null => {\n let open: { start: number; marker: string; depth: number } | null = null;\n let start = 0;\n for (const line of text.slice(0, position).split(\"\\n\")) {\n // A block inside a quote ends with that quote, for example at a blank line or an unquoted one.\n if (open && quoteDepth(line) < open.depth) open = null;\n if (open) {\n if (closesCodeFence(line, open.marker)) open = null;\n } else {\n const fence = fenceLine.exec(line);\n // A backtick in the info string makes the line inline code instead of a fence.\n if (fence && !(fence[1]![0] === \"`\" && fence[2]!.includes(\"`\"))) open = { start, marker: fence[1]!, depth: quoteDepth(line) };\n }\n start += line.length + 1;\n }\n return open && { start: open.start, marker: open.marker };\n};\n\nexport const isInCodeZone = (text: string, position: number): boolean => {\n if (openCodeFence(text, position)) return true;\n const before = text.slice(0, position);\n const line = before.slice(before.lastIndexOf(\"\\n\") + 1);\n return (line.match(/`/g) ?? []).length % 2 !== 0;\n};\n"],"mappings":"AAAA;AACA,MAAM,SAAS,GAAG,uCAAuC;;AAEzD;AACA,OAAO,MAAM,eAAe,GAAG,CAAC,IAAY,EAAE,MAAc,KAAc;EACxE,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;EAClC,OAAO,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAE,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,CAAC,CAAC;AAC/G,CAAC;;AAED;AACA,MAAM,UAAU,GAAI,IAAY,IAAa,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM;;AAEtG;AACA,OAAO,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,QAAgB,KAA+C;EACzG,IAAI,IAA6D,GAAG,IAAI;EACxE,IAAI,KAAK,GAAG,CAAC;EACb,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;IACtD;IACA,IAAI,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI;IACtD,IAAI,IAAI,EAAE;MACR,IAAI,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI;IACrD,CAAC,MAAM;MACL,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;MAClC;MACA,IAAI,KAAK,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG;QAAE,KAAK;QAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAE;QAAE,KAAK,EAAE,UAAU,CAAC,IAAI;MAAE,CAAC;IAC/H;IACA,KAAK,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;EAC1B;EACA,OAAO,IAAI,IAAI;IAAE,KAAK,EAAE,IAAI,CAAC,KAAK;IAAE,MAAM,EAAE,IAAI,CAAC;EAAO,CAAC;AAC3D,CAAC;AAED,OAAO,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,QAAgB,KAAc;EACvE,IAAI,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,IAAI;EAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;EACtC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;EACvD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,GAAG,CAAC,KAAK,CAAC;AAClD,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { i18n } from "@k2b/stdlib";
|
|
2
|
+
import { useLocale } from "../intl/locale";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SignatureInput's own strings. They live beside the component instead of in
|
|
6
|
+
* the shared catalog, so applications that never render a signature field do
|
|
7
|
+
* not ship them.
|
|
8
|
+
*/
|
|
9
|
+
const signatureMessages = i18n.define({
|
|
10
|
+
baseLocale: "en",
|
|
11
|
+
messages: {
|
|
12
|
+
en: {
|
|
13
|
+
method: "Signature method",
|
|
14
|
+
draw: "Draw",
|
|
15
|
+
type: "Type",
|
|
16
|
+
signHere: "Sign here",
|
|
17
|
+
drawArea: "Signature area. Draw with a finger, pen, or mouse.",
|
|
18
|
+
drawn: "Drawn signature",
|
|
19
|
+
typeName: "Type your name",
|
|
20
|
+
undo: "Undo"
|
|
21
|
+
},
|
|
22
|
+
de: {
|
|
23
|
+
method: "Art der Unterschrift",
|
|
24
|
+
draw: "Zeichnen",
|
|
25
|
+
type: "Tippen",
|
|
26
|
+
signHere: "Hier unterschreiben",
|
|
27
|
+
drawArea: "Unterschriftsfeld. Zeichne mit Finger, Stift oder Maus.",
|
|
28
|
+
drawn: "Gezeichnete Unterschrift",
|
|
29
|
+
typeName: "Namen eintippen",
|
|
30
|
+
undo: "Rückgängig"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
export const useSignatureMessages = () => {
|
|
35
|
+
const locale = useLocale();
|
|
36
|
+
return () => signatureMessages.resolve([locale()]).t;
|
|
37
|
+
};
|
|
38
|
+
export const checkSignatureMessages = () => signatureMessages.check();
|
|
39
|
+
//# sourceMappingURL=signature-messages.js.map
|