@refraction-ui/astro 0.16.0 → 0.17.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/composer/emoji-trigger.ts +51 -0
- package/dist/composer/index.ts +1 -0
- package/dist/composer/styles.ts +64 -9
- package/dist/emoji-picker/emoji-data.ts +242 -248
- package/dist/emoji-picker/emoji-dataset.generated.ts +1943 -0
- package/dist/emoji-picker/emoji-picker.styles.ts +11 -3
- package/dist/emoji-picker/index.ts +20 -0
- package/dist/emoji-picker/stickers.ts +146 -0
- package/dist/emoji-picker/twemoji.ts +60 -0
- package/dist/rich-editor/emoji.ts +10 -116
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createEmojiTrigger` — a ready-made `:` shortcode trigger backed by the shared
|
|
3
|
+
* emoji dataset (`@refraction-ui/emoji-picker`, ~1900 base emoji), so the
|
|
4
|
+
* composer's `:` menu is complete and matches the picker exactly (one source of
|
|
5
|
+
* truth, no divergence). The committed token is the native glyph.
|
|
6
|
+
*
|
|
7
|
+
* This module is side-effect free and imports the dataset lazily via the emoji
|
|
8
|
+
* search API, so it is only pulled into a bundle when `createEmojiTrigger` is
|
|
9
|
+
* actually referenced.
|
|
10
|
+
*/
|
|
11
|
+
import { searchEmojis } from '../emoji-picker/index.ts'
|
|
12
|
+
import type { ComposerCandidate, ComposerTrigger } from './types.js'
|
|
13
|
+
|
|
14
|
+
export interface EmojiTriggerOptions {
|
|
15
|
+
/** Trigger id. Default 'emoji'. */
|
|
16
|
+
id?: string
|
|
17
|
+
/** Symbol. Default ':'. */
|
|
18
|
+
symbol?: string
|
|
19
|
+
/** Max results surfaced to the menu. Default 8. */
|
|
20
|
+
maxResults?: number
|
|
21
|
+
/**
|
|
22
|
+
* Minimum query length before resolving (avoids flooding the menu with the
|
|
23
|
+
* whole set on a lone ':'). Default 1.
|
|
24
|
+
*/
|
|
25
|
+
minQueryLength?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Build a `:` emoji trigger. Typing `:fir` filters the full set; committing
|
|
30
|
+
* inserts the glyph (🔥). Pair it with the picker for the same coverage in both
|
|
31
|
+
* surfaces.
|
|
32
|
+
*/
|
|
33
|
+
export function createEmojiTrigger(options: EmojiTriggerOptions = {}): ComposerTrigger {
|
|
34
|
+
const { id = 'emoji', symbol = ':', maxResults = 8, minQueryLength = 1 } = options
|
|
35
|
+
return {
|
|
36
|
+
id,
|
|
37
|
+
symbol,
|
|
38
|
+
// The committed token is the glyph itself, not `:name:`.
|
|
39
|
+
toDisplay: (candidate: ComposerCandidate) =>
|
|
40
|
+
(candidate.metadata?.emoji as string | undefined) ?? candidate.display,
|
|
41
|
+
resolve: (query: string): ComposerCandidate[] => {
|
|
42
|
+
if (query.length < minQueryLength) return []
|
|
43
|
+
return searchEmojis(query, maxResults).map((entry) => ({
|
|
44
|
+
id: `${entry.shortcode}`,
|
|
45
|
+
display: `${entry.emoji} :${entry.shortcode}:`,
|
|
46
|
+
subtitle: entry.name,
|
|
47
|
+
metadata: { emoji: entry.emoji, shortcode: entry.shortcode },
|
|
48
|
+
}))
|
|
49
|
+
},
|
|
50
|
+
}
|
|
51
|
+
}
|
package/dist/composer/index.ts
CHANGED
package/dist/composer/styles.ts
CHANGED
|
@@ -6,13 +6,25 @@
|
|
|
6
6
|
|
|
7
7
|
import { cva } from '../shared/index.ts'
|
|
8
8
|
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Outer surface (the rounded card wrapping tray + field + action row).
|
|
11
|
+
* `surface` picks the resting fill: `outlined` (transparent-on-page card) or
|
|
12
|
+
* `filled` (a calm muted fill distinct from the page). Both keep a tasteful
|
|
13
|
+
* focus-visible ring on the pill — a hairline border plus a single-px ring, not
|
|
14
|
+
* a slammed saturated full-perimeter brand border.
|
|
15
|
+
*/
|
|
10
16
|
export const composerSurfaceVariants = cva({
|
|
11
17
|
base: [
|
|
12
|
-
'overflow-hidden rounded-2xl border
|
|
13
|
-
'transition-shadow
|
|
18
|
+
'overflow-hidden rounded-2xl border shadow-sm',
|
|
19
|
+
'transition-[box-shadow,border-color,background-color] duration-150 ease-out',
|
|
20
|
+
'focus-within:ring-1 focus-within:ring-ring focus-within:shadow-md',
|
|
21
|
+
'motion-reduce:transition-none',
|
|
14
22
|
].join(' '),
|
|
15
23
|
variants: {
|
|
24
|
+
surface: {
|
|
25
|
+
outlined: 'border-border bg-background focus-within:border-ring',
|
|
26
|
+
filled: 'border-border/50 bg-muted/50 focus-within:border-ring/70 focus-within:bg-background',
|
|
27
|
+
},
|
|
16
28
|
disabled: {
|
|
17
29
|
true: 'pointer-events-none opacity-60',
|
|
18
30
|
false: '',
|
|
@@ -23,6 +35,7 @@ export const composerSurfaceVariants = cva({
|
|
|
23
35
|
},
|
|
24
36
|
},
|
|
25
37
|
defaultVariants: {
|
|
38
|
+
surface: 'outlined',
|
|
26
39
|
disabled: 'false',
|
|
27
40
|
error: 'false',
|
|
28
41
|
},
|
|
@@ -35,9 +48,16 @@ export const composerFieldClass =
|
|
|
35
48
|
/** Attachment tray above the field, inside the dock. */
|
|
36
49
|
export const composerTrayClass = 'flex flex-wrap gap-2 px-3 pt-3'
|
|
37
50
|
|
|
38
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* A single attachment chip. Chips animate in on add (scale + fade) and, when
|
|
53
|
+
* the adapter marks one `exiting`, animate out faster before unmounting. Both
|
|
54
|
+
* degrade to opacity-only / instant under reduced motion.
|
|
55
|
+
*/
|
|
39
56
|
export const composerAttachmentChipVariants = cva({
|
|
40
|
-
base:
|
|
57
|
+
base: [
|
|
58
|
+
'inline-flex items-center gap-1 rounded-md bg-muted px-2 py-0.5 text-xs',
|
|
59
|
+
'origin-left transition-all duration-150 ease-out motion-reduce:transition-none',
|
|
60
|
+
].join(' '),
|
|
41
61
|
variants: {
|
|
42
62
|
status: {
|
|
43
63
|
pending: 'opacity-70',
|
|
@@ -45,9 +65,14 @@ export const composerAttachmentChipVariants = cva({
|
|
|
45
65
|
ready: '',
|
|
46
66
|
error: 'text-destructive',
|
|
47
67
|
},
|
|
68
|
+
exiting: {
|
|
69
|
+
true: 'scale-90 opacity-0 motion-reduce:scale-100',
|
|
70
|
+
false: 'motion-safe:animate-fade-in-scale',
|
|
71
|
+
},
|
|
48
72
|
},
|
|
49
73
|
defaultVariants: {
|
|
50
74
|
status: 'pending',
|
|
75
|
+
exiting: 'false',
|
|
51
76
|
},
|
|
52
77
|
})
|
|
53
78
|
|
|
@@ -55,9 +80,35 @@ export const composerAttachmentChipVariants = cva({
|
|
|
55
80
|
export const composerTokenPillClass =
|
|
56
81
|
'rounded bg-accent/40 px-0.5 text-accent-foreground'
|
|
57
82
|
|
|
58
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* The caret-anchored suggestion menu. Enters with an eased fade+scale from its
|
|
85
|
+
* bottom edge (it sits above the field); reduced motion drops the movement.
|
|
86
|
+
*/
|
|
59
87
|
export const composerMenuClass =
|
|
60
|
-
'z-20 w-72 overflow-hidden rounded-xl border border-border bg-popover shadow-lg'
|
|
88
|
+
'z-20 w-72 overflow-hidden rounded-xl border border-border bg-popover shadow-lg origin-bottom motion-safe:animate-fade-in-scale'
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The inline expression/accessory panel docked below the field. It is part of
|
|
92
|
+
* the composer's own stack (never a floating portal), so the textarea and the
|
|
93
|
+
* message in progress stay fully visible while the panel is open. Opens with an
|
|
94
|
+
* eased fade; reduced motion shows it instantly.
|
|
95
|
+
*/
|
|
96
|
+
export const composerAccessoryPanelClass =
|
|
97
|
+
'border-t border-border motion-safe:animate-fade-in'
|
|
98
|
+
|
|
99
|
+
/** The built-in expression-panel toggle button. */
|
|
100
|
+
export const composerAccessoryToggleVariants = cva({
|
|
101
|
+
base: 'flex h-8 w-8 items-center justify-center rounded-lg transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
102
|
+
variants: {
|
|
103
|
+
active: {
|
|
104
|
+
true: 'bg-accent text-foreground',
|
|
105
|
+
false: 'text-muted-foreground',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
defaultVariants: {
|
|
109
|
+
active: 'false',
|
|
110
|
+
},
|
|
111
|
+
})
|
|
61
112
|
|
|
62
113
|
/** A suggestion row; `active` follows keyboard/pointer last-input-wins. */
|
|
63
114
|
export const composerMenuItemVariants = cva({
|
|
@@ -87,9 +138,13 @@ export const composerCounterVariants = cva({
|
|
|
87
138
|
},
|
|
88
139
|
})
|
|
89
140
|
|
|
90
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* Primary action (send ⇄ stop swap driven by `{hasText, canSend, isBusy}`).
|
|
143
|
+
* The colour/affordance change eases; the adapter keys the button on busy so
|
|
144
|
+
* the swap pops in (scale) rather than snapping. Reduced motion keeps it calm.
|
|
145
|
+
*/
|
|
91
146
|
export const composerPrimaryActionVariants = cva({
|
|
92
|
-
base: 'flex h-9 w-9 items-center justify-center rounded-full transition',
|
|
147
|
+
base: 'flex h-9 w-9 items-center justify-center rounded-full transition-all duration-150 ease-out active:scale-95 motion-reduce:transition-none motion-reduce:active:scale-100 motion-safe:animate-scale-in',
|
|
93
148
|
variants: {
|
|
94
149
|
enabled: {
|
|
95
150
|
true: 'bg-primary text-primary-foreground hover:opacity-90',
|