@lovett/ui 0.0.11 → 0.2.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/dist/chunk-RBYWGBQ2.js +2752 -0
- package/dist/chunk-RBYWGBQ2.js.map +1 -0
- package/dist/index.d.ts +5574 -57
- package/dist/index.js +21650 -11206
- package/dist/index.js.map +1 -1
- package/dist/rich-composer-impl-5NO443A6.js +1859 -0
- package/dist/rich-composer-impl-5NO443A6.js.map +1 -0
- package/dist/styles.css +1570 -0
- package/dist/tokens.css +112 -0
- package/package.json +8 -1
- package/src/__tests__/avatar.test.tsx +272 -0
- package/src/__tests__/bar-chart.test.tsx +809 -0
- package/src/__tests__/board.test.tsx +420 -0
- package/src/__tests__/chart-math.test.ts +922 -0
- package/src/__tests__/chart-series.test.ts +339 -0
- package/src/__tests__/code-block.test.tsx +134 -0
- package/src/__tests__/display-popover.test.tsx +195 -0
- package/src/__tests__/display-store.test.tsx +307 -0
- package/src/__tests__/donut-chart.test.tsx +397 -0
- package/src/__tests__/dropdown-menu.test.tsx +156 -2
- package/src/__tests__/filter-menu.test.tsx +175 -0
- package/src/__tests__/gauge-ring.test.tsx +233 -0
- package/src/__tests__/line-chart.test.tsx +612 -0
- package/src/__tests__/ranked-bars.test.tsx +343 -0
- package/src/__tests__/remark-underline.test.ts +194 -0
- package/src/__tests__/sortable.test.tsx +394 -0
- package/src/__tests__/sparkline.test.tsx +368 -0
- package/src/__tests__/stat-layer.test.tsx +271 -0
- package/src/__tests__/stat-strip.test.tsx +175 -0
- package/src/__tests__/status.test.tsx +293 -0
- package/src/__tests__/tabs.test.tsx +303 -0
- package/src/__tests__/token-shape.test.ts +132 -2
- package/src/avatar.tsx +352 -0
- package/src/bar-chart.tsx +1214 -0
- package/src/board.tsx +658 -0
- package/src/chart-frame.tsx +960 -0
- package/src/chart-legend.tsx +304 -0
- package/src/chart-tooltip.tsx +267 -0
- package/src/code-block.tsx +62 -8
- package/src/delta-chip.tsx +263 -0
- package/src/detail/__tests__/activity-pane.test.tsx +369 -0
- package/src/detail/__tests__/detail-chrome.test.tsx +134 -0
- package/src/detail/__tests__/detail-surface.test.tsx +529 -0
- package/src/detail/__tests__/field-row.test.tsx +357 -0
- package/src/detail/activity-pane.tsx +611 -0
- package/src/detail/calendar.tsx +355 -0
- package/src/detail/detail-divider.tsx +261 -0
- package/src/detail/detail-header.tsx +287 -0
- package/src/detail/detail-menu.tsx +254 -0
- package/src/detail/detail-surface.tsx +1110 -0
- package/src/detail/field-list.tsx +196 -0
- package/src/detail/field-row.tsx +1131 -0
- package/src/detail/index.ts +58 -0
- package/src/detail/segmented-choice.tsx +94 -0
- package/src/detail/types.ts +129 -0
- package/src/display-popover.tsx +487 -0
- package/src/display-store.tsx +301 -0
- package/src/donut-chart.tsx +988 -0
- package/src/dropdown-menu.tsx +290 -19
- package/src/filter-core/EXPORTS.md +85 -0
- package/src/filter-core/__tests__/columns.test.ts +159 -0
- package/src/filter-core/__tests__/faceting.test.ts +193 -0
- package/src/filter-core/__tests__/filter-fns.test.ts +519 -0
- package/src/filter-core/__tests__/operators.test.ts +235 -0
- package/src/filter-core/__tests__/state.test.ts +268 -0
- package/src/filter-core/__tests__/url.test.ts +350 -0
- package/src/filter-core/columns.ts +134 -0
- package/src/filter-core/date-utils.ts +38 -0
- package/src/filter-core/examples/task-filter-columns.ts +121 -0
- package/src/filter-core/faceting.ts +120 -0
- package/src/filter-core/filter-fns.ts +335 -0
- package/src/filter-core/index.ts +105 -0
- package/src/filter-core/operators.ts +433 -0
- package/src/filter-core/state.ts +280 -0
- package/src/filter-core/types.ts +247 -0
- package/src/filter-core/url.ts +261 -0
- package/src/filter-dropdown.tsx +12 -0
- package/src/filter-menu.tsx +649 -0
- package/src/floating-drawer.tsx +19 -1
- package/src/gauge-ring.tsx +435 -0
- package/src/hue.ts +52 -0
- package/src/index.ts +303 -0
- package/src/kbd.tsx +27 -4
- package/src/lib/chart.ts +866 -0
- package/src/lib/focus.ts +43 -1
- package/src/lib/layer-stack.ts +30 -3
- package/src/lib/remark-underline.ts +443 -0
- package/src/lib/series.ts +169 -0
- package/src/line-chart.tsx +1176 -0
- package/src/markdown.tsx +26 -7
- package/src/modal.tsx +42 -18
- package/src/progress-ledger.tsx +304 -0
- package/src/ranked-bars.tsx +386 -0
- package/src/segmented-pill.tsx +32 -9
- package/src/sortable.tsx +520 -1
- package/src/sparkline.tsx +416 -0
- package/src/stat-card.tsx +376 -0
- package/src/stat-strip.tsx +327 -0
- package/src/status.tsx +215 -0
- package/src/styles.css +1570 -0
- package/src/tabs.tsx +206 -25
- package/src/task-card.tsx +610 -0
- package/src/thread/__tests__/comment-body-hostile.test.tsx +331 -0
- package/src/thread/__tests__/comment-tree.test.ts +151 -0
- package/src/thread/__tests__/emoji.test.ts +187 -0
- package/src/thread/__tests__/fixtures/thread-fixture.ts +252 -0
- package/src/thread/__tests__/link-preview-source.test.ts +120 -0
- package/src/thread/__tests__/link-preview.test.tsx +600 -0
- package/src/thread/__tests__/markdown-format.test.ts +82 -0
- package/src/thread/__tests__/markdown-spec.test.ts +469 -0
- package/src/thread/__tests__/relative-time.test.ts +71 -0
- package/src/thread/__tests__/rich-composer.test.tsx +799 -0
- package/src/thread/__tests__/scroll-caret.test.ts +58 -0
- package/src/thread/__tests__/suggestion-list.test.tsx +648 -0
- package/src/thread/__tests__/thread-scroll-ownership.test.tsx +88 -0
- package/src/thread/__tests__/thread.test.tsx +742 -0
- package/src/thread/__tests__/use-attachments.test.tsx +679 -0
- package/src/thread/actions.tsx +196 -0
- package/src/thread/attachments.tsx +1071 -0
- package/src/thread/comment-body.tsx +148 -0
- package/src/thread/comment-tree.ts +182 -0
- package/src/thread/comment.tsx +967 -0
- package/src/thread/composer-footer.tsx +125 -0
- package/src/thread/composer.tsx +319 -0
- package/src/thread/emoji.ts +283 -0
- package/src/thread/index.ts +153 -0
- package/src/thread/link-preview.tsx +341 -0
- package/src/thread/markdown-format.ts +155 -0
- package/src/thread/markdown-spec.ts +754 -0
- package/src/thread/rail.tsx +372 -0
- package/src/thread/reactions.tsx +415 -0
- package/src/thread/relative-time.tsx +94 -0
- package/src/thread/rich-composer-impl.tsx +1601 -0
- package/src/thread/rich-composer.tsx +195 -0
- package/src/thread/scroll-caret.ts +37 -0
- package/src/thread/suggestion-list.tsx +182 -0
- package/src/thread/thread.tsx +718 -0
- package/src/thread/types.ts +232 -0
- package/src/thread/use-attachments.ts +598 -0
- package/src/thread/use-now.ts +73 -0
- package/src/thread/use-thread.ts +316 -0
- package/src/tokens.css +112 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emoji — the curated shortcode table behind the `:` picker (ADR-149 D3).
|
|
3
|
+
*
|
|
4
|
+
* A HAND-MAINTAINED table, not a dataset. `emojibase-data` and friends are
|
|
5
|
+
* ~1 MB and would load with the composer chunk for a feature whose whole job
|
|
6
|
+
* is to save four keystrokes. This is roughly 150 entries covering what this
|
|
7
|
+
* product's people actually reach for; adding one is a one-line PR against
|
|
8
|
+
* `EMOJI_ROWS` below, and that is the intended maintenance model.
|
|
9
|
+
*
|
|
10
|
+
* EVERY GLYPH IS WRITTEN AS A `\u{...}` ESCAPE, NEVER A RAW BYTE. A raw high
|
|
11
|
+
* byte makes a source file grep as binary and blinds the CLAUDE.md §8 gates —
|
|
12
|
+
* the lesson from ADR-147 D8, restated as ADR-149 AC#9. This file must stay
|
|
13
|
+
* `US-ASCII`/`UTF-8 text` under `file(1)` with zero bytes >= 0x80, and so must
|
|
14
|
+
* every test that names a glyph.
|
|
15
|
+
*
|
|
16
|
+
* DIALECT: GitHub shortcodes, the most widely known. Where Slack, Teams or a
|
|
17
|
+
* person's muscle memory spells one differently, the difference is an ALIAS on
|
|
18
|
+
* the same entry, never a second entry — the owner's `:side-eye:` is an alias
|
|
19
|
+
* of GitHub's `roll_eyes`. `-` and `_` are interchangeable everywhere (the
|
|
20
|
+
* query and the table are both normalized), so `:side-eye:` and `:side_eye:`
|
|
21
|
+
* are the same lookup.
|
|
22
|
+
*
|
|
23
|
+
* OUT OF SCOPE for v1 (D3): skin-tone modifiers and ZWJ sequences. They
|
|
24
|
+
* multiply the table and need a per-user preference to be anything but a
|
|
25
|
+
* gimmick.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export interface EmojiEntry {
|
|
29
|
+
/** The canonical GitHub shortcode, without the surrounding colons. */
|
|
30
|
+
readonly name: string
|
|
31
|
+
/** The character itself. Written as `\u{...}` at the source level. */
|
|
32
|
+
readonly glyph: string
|
|
33
|
+
/** Other spellings that resolve to this entry (Slack/Teams/plain English). */
|
|
34
|
+
readonly aliases: readonly string[]
|
|
35
|
+
/** Search terms that are not names — `:party:` has to find `tada`. */
|
|
36
|
+
readonly keywords: readonly string[]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* One row per emoji: `[name, glyph, aliases, keywords]`, the two lists
|
|
41
|
+
* pipe-joined so a row stays one line. Expanded once, below.
|
|
42
|
+
*/
|
|
43
|
+
type EmojiRow = readonly [name: string, glyph: string, aliases: string, keywords: string]
|
|
44
|
+
|
|
45
|
+
const EMOJI_ROWS: readonly EmojiRow[] = [
|
|
46
|
+
/* ── Faces ───────────────────────────────────────────────────────────── */
|
|
47
|
+
['grinning', '\u{1F600}', '', 'smile|happy|grin'],
|
|
48
|
+
['smiley', '\u{1F603}', '', 'happy|joy|cheerful'],
|
|
49
|
+
['smile', '\u{1F604}', '', 'happy|joy|laugh'],
|
|
50
|
+
['grin', '\u{1F601}', '', 'happy|beam|pleased'],
|
|
51
|
+
['laughing', '\u{1F606}', 'satisfied', 'haha|lol|funny'],
|
|
52
|
+
['sweat_smile', '\u{1F605}', '', 'phew|relief|nervous'],
|
|
53
|
+
['joy', '\u{1F602}', 'lol', 'laugh|tears|haha|funny'],
|
|
54
|
+
['rofl', '\u{1F923}', 'rolling_on_the_floor_laughing', 'lol|haha|hilarious'],
|
|
55
|
+
['slightly_smiling_face', '\u{1F642}', 'slight_smile', 'smile|fine|ok'],
|
|
56
|
+
['upside_down_face', '\u{1F643}', 'upside_down', 'irony|sarcasm|silly'],
|
|
57
|
+
['wink', '\u{1F609}', '', 'flirt|joke|kidding'],
|
|
58
|
+
['blush', '\u{1F60A}', '', 'happy|shy|smile'],
|
|
59
|
+
['innocent', '\u{1F607}', '', 'angel|halo|good'],
|
|
60
|
+
['heart_eyes', '\u{1F60D}', '', 'love|adore|crush'],
|
|
61
|
+
['star_struck', '\u{1F929}', '', 'amazed|wow|excited'],
|
|
62
|
+
['yum', '\u{1F60B}', '', 'delicious|tasty|tongue'],
|
|
63
|
+
['raised_eyebrow', '\u{1F928}', 'face_with_raised_eyebrow', 'skeptical|doubt|suspicious'],
|
|
64
|
+
['neutral_face', '\u{1F610}', '', 'meh|blank|straight'],
|
|
65
|
+
['expressionless', '\u{1F611}', '', 'blank|meh|deadpan'],
|
|
66
|
+
['smirk', '\u{1F60F}', '', 'smug|sly|knowing'],
|
|
67
|
+
['unamused', '\u{1F612}', '', 'meh|annoyed|unimpressed'],
|
|
68
|
+
['roll_eyes', '\u{1F644}', 'face_with_rolling_eyes|side_eye|sideeye', 'whatever|annoyed|sarcasm|really'],
|
|
69
|
+
['grimacing', '\u{1F62C}', '', 'awkward|eek|yikes'],
|
|
70
|
+
['relieved', '\u{1F60C}', '', 'phew|calm|content'],
|
|
71
|
+
['pensive', '\u{1F614}', '', 'sad|thoughtful|wistful'],
|
|
72
|
+
['sleeping', '\u{1F634}', '', 'zzz|asleep|bored'],
|
|
73
|
+
['exploding_head', '\u{1F92F}', 'mind_blown', 'mindblown|whoa|shocked'],
|
|
74
|
+
['partying_face', '\u{1F973}', '', 'birthday|hooray|horn'],
|
|
75
|
+
['sunglasses', '\u{1F60E}', '', 'cool|deal|smooth'],
|
|
76
|
+
['nerd_face', '\u{1F913}', 'nerd', 'geek|glasses|smart'],
|
|
77
|
+
['monocle_face', '\u{1F9D0}', 'monocle', 'inspect|scrutinize|examine'],
|
|
78
|
+
['confused', '\u{1F615}', '', 'unsure|puzzled'],
|
|
79
|
+
['slightly_frowning_face', '\u{1F641}', 'slight_frown', 'sad|frown'],
|
|
80
|
+
['open_mouth', '\u{1F62E}', '', 'wow|surprise|shock'],
|
|
81
|
+
['flushed', '\u{1F633}', '', 'blush|embarrassed|shy'],
|
|
82
|
+
['pleading_face', '\u{1F97A}', 'pleading', 'puppy|beg|please'],
|
|
83
|
+
['fearful', '\u{1F628}', '', 'scared|afraid|yikes'],
|
|
84
|
+
['cry', '\u{1F622}', '', 'sad|tear|upset'],
|
|
85
|
+
['sob', '\u{1F62D}', 'crying', 'bawl|sad|tears'],
|
|
86
|
+
['scream', '\u{1F631}', '', 'horror|shock|panic'],
|
|
87
|
+
['disappointed', '\u{1F61E}', '', 'sad|letdown'],
|
|
88
|
+
['weary', '\u{1F629}', '', 'exhausted|tired|done'],
|
|
89
|
+
['tired_face', '\u{1F62B}', '', 'exhausted|fed_up'],
|
|
90
|
+
['yawning_face', '\u{1F971}', 'yawn', 'bored|sleepy|tired'],
|
|
91
|
+
['rage', '\u{1F621}', 'enraged', 'angry|mad|furious'],
|
|
92
|
+
['angry', '\u{1F620}', '', 'mad|annoyed|cross'],
|
|
93
|
+
['thinking', '\u{1F914}', 'thinking_face|hmm', 'ponder|consider|unsure'],
|
|
94
|
+
['shushing_face', '\u{1F92B}', 'shush', 'quiet|secret|hush'],
|
|
95
|
+
['zipper_mouth_face', '\u{1F910}', 'zipper_mouth', 'secret|quiet|sealed'],
|
|
96
|
+
['saluting_face', '\u{1FAE1}', 'salute', 'respect|acknowledge|yessir'],
|
|
97
|
+
['face_holding_back_tears', '\u{1F979}', 'holding_back_tears', 'emotional|touched|proud'],
|
|
98
|
+
['clown_face', '\u{1F921}', 'clown', 'joke|silly|circus'],
|
|
99
|
+
['ghost', '\u{1F47B}', '', 'boo|spooky|halloween'],
|
|
100
|
+
['skull', '\u{1F480}', '', 'dead|rip|died'],
|
|
101
|
+
['robot', '\u{1F916}', 'robot_face', 'bot|automation|machine'],
|
|
102
|
+
['see_no_evil', '\u{1F648}', '', 'monkey|hide|oops'],
|
|
103
|
+
['poop', '\u{1F4A9}', 'hankey', 'bad|garbage|rubbish'],
|
|
104
|
+
|
|
105
|
+
/* ── Hands and body ──────────────────────────────────────────────────── */
|
|
106
|
+
['+1', '\u{1F44D}', 'thumbsup|thumbs_up|like', 'yes|agree|approve|ok'],
|
|
107
|
+
['-1', '\u{1F44E}', 'thumbsdown|thumbs_down|dislike', 'no|disagree|reject'],
|
|
108
|
+
['ok_hand', '\u{1F44C}', '', 'perfect|fine|good'],
|
|
109
|
+
['clap', '\u{1F44F}', '', 'applause|bravo|well_done'],
|
|
110
|
+
['raised_hands', '\u{1F64C}', '', 'praise|hooray|celebrate'],
|
|
111
|
+
['pray', '\u{1F64F}', 'folded_hands', 'please|thanks|thank_you|hope'],
|
|
112
|
+
['muscle', '\u{1F4AA}', 'flex', 'strong|strength|power'],
|
|
113
|
+
['wave', '\u{1F44B}', '', 'hi|hello|bye|greeting'],
|
|
114
|
+
['point_right', '\u{1F449}', '', 'this|direction|there'],
|
|
115
|
+
['point_left', '\u{1F448}', '', 'that|direction|back'],
|
|
116
|
+
['crossed_fingers', '\u{1F91E}', 'fingers_crossed', 'luck|hope|wish'],
|
|
117
|
+
['handshake', '\u{1F91D}', '', 'deal|agree|partner'],
|
|
118
|
+
['writing_hand', '\u{270D}\u{FE0F}', 'writing', 'note|sign|draft'],
|
|
119
|
+
['eyes', '\u{1F440}', '', 'look|watch|reviewing|see'],
|
|
120
|
+
['brain', '\u{1F9E0}', '', 'smart|idea|think'],
|
|
121
|
+
['facepalm', '\u{1F926}', '', 'oops|ugh|smh'],
|
|
122
|
+
['shrug', '\u{1F937}', '', 'dunno|idk|whatever'],
|
|
123
|
+
['raising_hand', '\u{1F64B}', 'raise_hand', 'question|volunteer|me'],
|
|
124
|
+
|
|
125
|
+
/* ── Celebration and energy ──────────────────────────────────────────── */
|
|
126
|
+
['tada', '\u{1F389}', 'party|hooray|celebrate', 'confetti|launch|ship|shipped|done'],
|
|
127
|
+
['sparkles', '\u{2728}', '', 'shiny|magic|new|clean'],
|
|
128
|
+
['fire', '\u{1F525}', 'flame|lit', 'hot|burning|great'],
|
|
129
|
+
['rocket', '\u{1F680}', '', 'launch|ship|deploy|fast'],
|
|
130
|
+
['boom', '\u{1F4A5}', 'collision', 'explode|bang|impact'],
|
|
131
|
+
['zap', '\u{26A1}', 'lightning', 'fast|power|energy'],
|
|
132
|
+
['star', '\u{2B50}', '', 'favourite|rating|good'],
|
|
133
|
+
['100', '\u{1F4AF}', 'hundred|perfect', 'score|agree|exactly'],
|
|
134
|
+
['trophy', '\u{1F3C6}', '', 'win|award|champion'],
|
|
135
|
+
['dart', '\u{1F3AF}', 'bullseye|target', 'goal|aim|precise'],
|
|
136
|
+
['crown', '\u{1F451}', '', 'king|queen|best'],
|
|
137
|
+
['gem', '\u{1F48E}', 'diamond', 'jewel|valuable|premium'],
|
|
138
|
+
['bulb', '\u{1F4A1}', 'idea|light_bulb', 'insight|bright|suggestion'],
|
|
139
|
+
|
|
140
|
+
/* ── Work, status and objects ────────────────────────────────────────── */
|
|
141
|
+
['moneybag', '\u{1F4B0}', 'money', 'budget|cash|spend'],
|
|
142
|
+
['chart_with_upwards_trend', '\u{1F4C8}', 'chart_up|trending_up', 'growth|increase|up'],
|
|
143
|
+
['chart_with_downwards_trend', '\u{1F4C9}', 'chart_down|trending_down', 'decline|decrease|down'],
|
|
144
|
+
['bar_chart', '\u{1F4CA}', 'chart', 'data|report|stats'],
|
|
145
|
+
['clipboard', '\u{1F4CB}', '', 'list|notes|tasks'],
|
|
146
|
+
['calendar', '\u{1F4C5}', 'date', 'schedule|day|meeting'],
|
|
147
|
+
['pushpin', '\u{1F4CC}', 'pin', 'pinned|note|important'],
|
|
148
|
+
['paperclip', '\u{1F4CE}', 'attachment', 'attach|file|clip'],
|
|
149
|
+
['mag', '\u{1F50D}', 'search|magnifying_glass', 'find|look|zoom'],
|
|
150
|
+
['lock', '\u{1F512}', '', 'secure|private|closed'],
|
|
151
|
+
['unlock', '\u{1F513}', '', 'open|access'],
|
|
152
|
+
['key', '\u{1F511}', '', 'access|password|secret'],
|
|
153
|
+
['bell', '\u{1F514}', 'notification', 'alert|ring|remind'],
|
|
154
|
+
['no_bell', '\u{1F515}', 'mute', 'silence|quiet|off'],
|
|
155
|
+
['hourglass', '\u{231B}', 'waiting', 'time|wait|pending'],
|
|
156
|
+
['alarm_clock', '\u{23F0}', 'alarm', 'time|remind|deadline'],
|
|
157
|
+
['stopwatch', '\u{23F1}\u{FE0F}', 'timer', 'time|measure|speed'],
|
|
158
|
+
['warning', '\u{26A0}\u{FE0F}', 'caution', 'careful|alert|risk'],
|
|
159
|
+
['no_entry', '\u{26D4}', 'blocked', 'stop|forbidden|blocker'],
|
|
160
|
+
['white_check_mark', '\u{2705}', 'check|done', 'complete|yes|approved|shipped'],
|
|
161
|
+
['heavy_check_mark', '\u{2714}\u{FE0F}', 'checkmark|tick', 'done|yes|verified'],
|
|
162
|
+
['x', '\u{274C}', 'cross_mark', 'no|wrong|cancel|failed'],
|
|
163
|
+
['question', '\u{2753}', '', 'help|ask|unknown'],
|
|
164
|
+
['exclamation', '\u{2757}', 'heavy_exclamation_mark', 'important|alert'],
|
|
165
|
+
['construction', '\u{1F6A7}', 'wip', 'work_in_progress|building|roadworks'],
|
|
166
|
+
['hammer', '\u{1F528}', '', 'build|fix|tool'],
|
|
167
|
+
['wrench', '\u{1F527}', '', 'fix|tool|maintenance'],
|
|
168
|
+
['gear', '\u{2699}\u{FE0F}', 'settings', 'config|cog|options'],
|
|
169
|
+
['bug', '\u{1F41B}', '', 'defect|issue|error'],
|
|
170
|
+
['computer', '\u{1F4BB}', 'laptop', 'code|work|dev'],
|
|
171
|
+
['email', '\u{2709}\u{FE0F}', 'envelope', 'mail|message|send'],
|
|
172
|
+
['package', '\u{1F4E6}', '', 'box|release|ship|delivery'],
|
|
173
|
+
['memo', '\u{1F4DD}', 'note|pencil', 'write|notes|edit'],
|
|
174
|
+
['art', '\u{1F3A8}', 'palette', 'creative|paint|design'],
|
|
175
|
+
['speech_balloon', '\u{1F4AC}', 'comment', 'talk|message|chat'],
|
|
176
|
+
['thought_balloon', '\u{1F4AD}', 'thought', 'idea|think|dream'],
|
|
177
|
+
['mega', '\u{1F4E3}', 'megaphone|announce', 'announcement|shout|promote'],
|
|
178
|
+
['link', '\u{1F517}', '', 'url|chain|connect'],
|
|
179
|
+
['globe_with_meridians', '\u{1F310}', 'globe', 'internet|web|world'],
|
|
180
|
+
|
|
181
|
+
/* ── Hearts ──────────────────────────────────────────────────────────── */
|
|
182
|
+
['heart', '\u{2764}\u{FE0F}', 'red_heart|love', 'like|adore'],
|
|
183
|
+
['broken_heart', '\u{1F494}', '', 'sad|heartbreak'],
|
|
184
|
+
['sparkling_heart', '\u{1F496}', '', 'love|sparkle'],
|
|
185
|
+
['two_hearts', '\u{1F495}', '', 'love|cute'],
|
|
186
|
+
|
|
187
|
+
/* ── Nature ──────────────────────────────────────────────────────────── */
|
|
188
|
+
['sunny', '\u{2600}\u{FE0F}', 'sun', 'weather|clear|bright'],
|
|
189
|
+
['rainbow', '\u{1F308}', '', 'colour|pride|hope'],
|
|
190
|
+
['seedling', '\u{1F331}', 'sprout', 'grow|new|plant'],
|
|
191
|
+
['four_leaf_clover', '\u{1F340}', 'clover', 'luck|lucky'],
|
|
192
|
+
['unicorn', '\u{1F984}', '', 'magic|rare|special'],
|
|
193
|
+
|
|
194
|
+
/* ── Food and drink ──────────────────────────────────────────────────── */
|
|
195
|
+
['coffee', '\u{2615}', 'cafe', 'caffeine|morning|espresso'],
|
|
196
|
+
['beer', '\u{1F37A}', '', 'drink|cheers|friday'],
|
|
197
|
+
['champagne', '\u{1F37E}', '', 'celebrate|launch|cheers'],
|
|
198
|
+
['clinking_glasses', '\u{1F942}', 'cheers', 'toast|celebrate'],
|
|
199
|
+
['pizza', '\u{1F355}', '', 'food|slice'],
|
|
200
|
+
['birthday', '\u{1F382}', 'birthday_cake', 'cake|celebrate'],
|
|
201
|
+
|
|
202
|
+
/* ── Play ────────────────────────────────────────────────────────────── */
|
|
203
|
+
['video_game', '\u{1F3AE}', 'gamepad', 'play|gaming'],
|
|
204
|
+
['gift', '\u{1F381}', 'present', 'birthday|surprise'],
|
|
205
|
+
]
|
|
206
|
+
|
|
207
|
+
function splitList(value: string): readonly string[] {
|
|
208
|
+
return value === '' ? [] : value.split('|')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** The table, expanded. Order is the tie-break in {@link searchEmoji}. */
|
|
212
|
+
export const THREAD_EMOJI: readonly EmojiEntry[] = EMOJI_ROWS.map(
|
|
213
|
+
([name, glyph, aliases, keywords]) => ({
|
|
214
|
+
name,
|
|
215
|
+
glyph,
|
|
216
|
+
aliases: splitList(aliases),
|
|
217
|
+
keywords: splitList(keywords),
|
|
218
|
+
}),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* One spelling rule for both sides of the lookup: case-insensitive, `-` and
|
|
223
|
+
* `_` interchangeable, surrounding colons ignored. That is what makes the
|
|
224
|
+
* owner's `:side-eye:` and GitHub's `:side_eye:` the same key without a second
|
|
225
|
+
* table row.
|
|
226
|
+
*/
|
|
227
|
+
export function normalizeShortcode(value: string): string {
|
|
228
|
+
return value.trim().toLowerCase().replace(/^:+|:+$/g, '').replaceAll('-', '_')
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const BY_SHORTCODE: ReadonlyMap<string, EmojiEntry> = (() => {
|
|
232
|
+
const map = new Map<string, EmojiEntry>()
|
|
233
|
+
for (const entry of THREAD_EMOJI) {
|
|
234
|
+
for (const code of [entry.name, ...entry.aliases]) {
|
|
235
|
+
const key = normalizeShortcode(code)
|
|
236
|
+
// First writer wins, so a canonical name can never be shadowed by an
|
|
237
|
+
// alias added later in the table.
|
|
238
|
+
if (!map.has(key)) map.set(key, entry)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return map
|
|
242
|
+
})()
|
|
243
|
+
|
|
244
|
+
/** Resolve one shortcode — `tada`, `:tada:`, `side-eye` — to its entry. */
|
|
245
|
+
export function emojiByShortcode(code: string): EmojiEntry | undefined {
|
|
246
|
+
return BY_SHORTCODE.get(normalizeShortcode(code))
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Rank, most specific first: an exact name, an exact alias, an exact keyword,
|
|
251
|
+
* then the prefix forms of each. `:party:` therefore finds `tada` (alias,
|
|
252
|
+
* exact) ahead of `partying_face` (name, prefix) — D3's worked example.
|
|
253
|
+
* Anything that matches nothing scores `null` and is dropped.
|
|
254
|
+
*/
|
|
255
|
+
function score(entry: EmojiEntry, query: string): number | null {
|
|
256
|
+
if (entry.name === query) return 0
|
|
257
|
+
if (entry.aliases.includes(query)) return 1
|
|
258
|
+
if (entry.keywords.includes(query)) return 2
|
|
259
|
+
if (entry.name.startsWith(query)) return 3
|
|
260
|
+
if (entry.aliases.some((alias) => alias.startsWith(query))) return 4
|
|
261
|
+
if (entry.keywords.some((keyword) => keyword.startsWith(query))) return 5
|
|
262
|
+
return null
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** How many options the popup shows at once. */
|
|
266
|
+
export const EMOJI_RESULT_LIMIT = 8
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Prefix search over names, aliases and keywords (D4). An empty query returns
|
|
270
|
+
* nothing on purpose — the `:` trigger has a two-character threshold, and a
|
|
271
|
+
* bare colon must stay punctuation.
|
|
272
|
+
*/
|
|
273
|
+
export function searchEmoji(query: string, limit: number = EMOJI_RESULT_LIMIT): readonly EmojiEntry[] {
|
|
274
|
+
const normalized = normalizeShortcode(query)
|
|
275
|
+
if (normalized === '') return []
|
|
276
|
+
const ranked: { readonly entry: EmojiEntry; readonly rank: number; readonly order: number }[] = []
|
|
277
|
+
for (const [order, entry] of THREAD_EMOJI.entries()) {
|
|
278
|
+
const rank = score(entry, normalized)
|
|
279
|
+
if (rank !== null) ranked.push({ entry, rank, order })
|
|
280
|
+
}
|
|
281
|
+
ranked.sort((a, b) => (a.rank === b.rank ? a.order - b.order : a.rank - b.rank))
|
|
282
|
+
return ranked.slice(0, limit).map((match) => match.entry)
|
|
283
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lovett/ui — thread primitive (ADR-147 T3).
|
|
3
|
+
*
|
|
4
|
+
* A headless core plus one styled skin. Entity-agnostic by construction: it
|
|
5
|
+
* takes already-shaped data and reports intent through callbacks. It owns no
|
|
6
|
+
* fetch client and no base URL — T4 wires it to the API.
|
|
7
|
+
*
|
|
8
|
+
* Re-exported from packages/ui/src/index.ts. The `.ds-thread` radius
|
|
9
|
+
* declaration lives in styles.css (see the THREAD block there), not in a
|
|
10
|
+
* per-component stylesheet — the package ships two consumer stylesheets and
|
|
11
|
+
* has no CSS loader in its tsup build.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export { Thread } from './thread'
|
|
15
|
+
export type { ThreadProps, ThreadParticipant } from './thread'
|
|
16
|
+
|
|
17
|
+
export { useThread, DEFAULT_MAX_DEPTH, DEFAULT_REPLIES_VISIBLE } from './use-thread'
|
|
18
|
+
export type { UseThreadOptions, UseThreadResult, VisibleReplies } from './use-thread'
|
|
19
|
+
|
|
20
|
+
export { CommentItem } from './comment'
|
|
21
|
+
export type { CommentItemProps, ThreadRenderContext } from './comment'
|
|
22
|
+
|
|
23
|
+
export { CommentActions } from './actions'
|
|
24
|
+
export type { CommentActionsProps } from './actions'
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
CollapsedReplies,
|
|
28
|
+
DEFAULT_INDENT_CLAMP_DEPTH,
|
|
29
|
+
LineIcon,
|
|
30
|
+
ThreadConnector,
|
|
31
|
+
ThreadRail,
|
|
32
|
+
ThreadTrunkSegment,
|
|
33
|
+
} from './rail'
|
|
34
|
+
export type { CollapsedRepliesProps, ThreadConnectorProps, ThreadRailProps } from './rail'
|
|
35
|
+
|
|
36
|
+
export { ThreadComposer } from './composer'
|
|
37
|
+
export type { ThreadComposerProps } from './composer'
|
|
38
|
+
|
|
39
|
+
// The rich composer's SHELL only (ADR-148 D5). `rich-composer-impl.tsx` and
|
|
40
|
+
// `markdown-spec.ts` import TipTap statically and are reached exclusively
|
|
41
|
+
// through the shell's lazy boundary — re-exporting either here would pull
|
|
42
|
+
// ProseMirror into every consumer of the barrel.
|
|
43
|
+
export { RichThreadComposer } from './rich-composer'
|
|
44
|
+
export type { RichComposerAttachmentProps, RichThreadComposerProps } from './rich-composer'
|
|
45
|
+
|
|
46
|
+
// ADR-149 — the `@` and `:` picker.
|
|
47
|
+
//
|
|
48
|
+
// TYPES ONLY, and that is a decision rather than an oversight. `emoji.ts` and
|
|
49
|
+
// `suggestion-list.tsx` are both TipTap-free, so exporting their VALUES here
|
|
50
|
+
// would not pull in ProseMirror — but tsup would still hoist them into the
|
|
51
|
+
// shared chunk that `dist/index.js` imports eagerly, and AC#10 says the
|
|
52
|
+
// shortcode table loads with the COMPOSER, never with a thread list. Measured:
|
|
53
|
+
// with the value exports in place the table landed in the eager chunk; without
|
|
54
|
+
// them it sits in `rich-composer-impl-*.js` behind the lazy boundary.
|
|
55
|
+
//
|
|
56
|
+
// A host needs no value from either: it supplies `mentionItems` and the
|
|
57
|
+
// composer does the rest. Both modules stay reachable by direct path for the
|
|
58
|
+
// tests, exactly as `markdown-spec.ts` is.
|
|
59
|
+
export type { SuggestionListProps, SuggestionOption } from './suggestion-list'
|
|
60
|
+
export type { EmojiEntry } from './emoji'
|
|
61
|
+
|
|
62
|
+
// Attachments, GIFs and paste-to-file (ADR-151). Safe in the barrel: no TipTap
|
|
63
|
+
// and no ProseMirror — the rich composer's shell is still the only lazy seam.
|
|
64
|
+
export {
|
|
65
|
+
ATTACHMENT_ACCEPT,
|
|
66
|
+
AttachmentButton,
|
|
67
|
+
AttachmentDropZone,
|
|
68
|
+
AttachmentGif,
|
|
69
|
+
AttachmentImage,
|
|
70
|
+
AttachmentLightbox,
|
|
71
|
+
AttachmentPlaceholder,
|
|
72
|
+
AttachmentTray,
|
|
73
|
+
GifPicker,
|
|
74
|
+
formatAttachmentSize,
|
|
75
|
+
usePrefersReducedMotion,
|
|
76
|
+
} from './attachments'
|
|
77
|
+
export type {
|
|
78
|
+
AttachmentButtonProps,
|
|
79
|
+
AttachmentDropZoneProps,
|
|
80
|
+
AttachmentGifProps,
|
|
81
|
+
AttachmentImageProps,
|
|
82
|
+
AttachmentLightboxProps,
|
|
83
|
+
AttachmentTrayProps,
|
|
84
|
+
GifPickerProps,
|
|
85
|
+
GifPickerResult,
|
|
86
|
+
} from './attachments'
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
ATTACHMENT_LIMITS,
|
|
90
|
+
GIF_SEARCH_DEBOUNCE_MS,
|
|
91
|
+
PASTE_ATTACHMENT_THRESHOLD,
|
|
92
|
+
pastedTextFilename,
|
|
93
|
+
shouldAttachPaste,
|
|
94
|
+
useAttachmentUrl,
|
|
95
|
+
useAttachments,
|
|
96
|
+
} from './use-attachments'
|
|
97
|
+
export type {
|
|
98
|
+
AttachmentTicketLike,
|
|
99
|
+
ComposerAttachment,
|
|
100
|
+
ComposerAttachmentKind,
|
|
101
|
+
ComposerAttachmentState,
|
|
102
|
+
UseAttachmentsOptions,
|
|
103
|
+
UseAttachmentsResult,
|
|
104
|
+
} from './use-attachments'
|
|
105
|
+
|
|
106
|
+
// Link previews (ADR-150 D8). No TipTap, no parser, no fetch client — the
|
|
107
|
+
// worker does every dangerous part and this renders the strings it stored.
|
|
108
|
+
export { LinkPreview, LINK_PREVIEW_DEFAULT_ASPECT } from './link-preview'
|
|
109
|
+
export type { LinkPreviewProps } from './link-preview'
|
|
110
|
+
|
|
111
|
+
export { applyMarkdownFormat } from './markdown-format'
|
|
112
|
+
export type { MarkdownFormat, MarkdownEdit } from './markdown-format'
|
|
113
|
+
|
|
114
|
+
export { CommentBody, parseMentionHref } from './comment-body'
|
|
115
|
+
export type { CommentBodyProps, MentionTarget, MentionTargetType } from './comment-body'
|
|
116
|
+
|
|
117
|
+
export { ReactionBar, CommentVote, REACTION_META } from './reactions'
|
|
118
|
+
export type { ReactionBarProps, CommentVoteProps } from './reactions'
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
RelativeTime,
|
|
122
|
+
formatRelativeTime,
|
|
123
|
+
formatAbsoluteTime,
|
|
124
|
+
toIsoTimestamp,
|
|
125
|
+
} from './relative-time'
|
|
126
|
+
export type { RelativeTimeProps } from './relative-time'
|
|
127
|
+
|
|
128
|
+
export {
|
|
129
|
+
buildCommentTree,
|
|
130
|
+
countCommentTree,
|
|
131
|
+
countDescendants,
|
|
132
|
+
engagementScore,
|
|
133
|
+
sortCommentTree,
|
|
134
|
+
} from './comment-tree'
|
|
135
|
+
|
|
136
|
+
export { useNowTick } from './use-now'
|
|
137
|
+
|
|
138
|
+
export { THREAD_REACTION_KEYS } from './types'
|
|
139
|
+
export type {
|
|
140
|
+
CommentDeliveryState,
|
|
141
|
+
CommentNode,
|
|
142
|
+
MentionSuggestionItem,
|
|
143
|
+
ThreadAttachment,
|
|
144
|
+
ThreadAttachmentKind,
|
|
145
|
+
ThreadAuthor,
|
|
146
|
+
ThreadComment,
|
|
147
|
+
ThreadEngagement,
|
|
148
|
+
ThreadLinkPreview,
|
|
149
|
+
ThreadReactionCount,
|
|
150
|
+
ThreadReactionKey,
|
|
151
|
+
ThreadSort,
|
|
152
|
+
ThreadVote,
|
|
153
|
+
} from './types'
|