@rtzll/reflow 0.5.0 → 0.6.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/avatar.css +116 -0
- package/dist/avatar.d.ts +42 -0
- package/dist/avatar.js +74 -0
- package/dist/basic.d.ts +1 -20
- package/dist/basic.js +1 -20
- package/dist/chat-layout.css +121 -0
- package/dist/chat-layout.d.ts +24 -0
- package/dist/chat-layout.js +108 -0
- package/dist/citation.css +119 -0
- package/dist/citation.d.ts +35 -0
- package/dist/citation.js +45 -0
- package/dist/code-block.css +292 -0
- package/dist/code-block.d.ts +59 -0
- package/dist/code-block.js +117 -0
- package/dist/colors.d.ts +21 -0
- package/dist/colors.js +21 -0
- package/dist/compositions.css +51 -0
- package/dist/compositions.d.ts +8 -1
- package/dist/compositions.js +2 -0
- package/dist/drawer.css +33 -37
- package/dist/highlight.d.ts +36 -0
- package/dist/highlight.js +134 -0
- package/dist/hover-card.d.ts +4 -0
- package/dist/hover-card.js +5 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/styles.css +4 -0
- package/dist/toaster.js +3 -2
- package/package.json +19 -3
package/dist/compositions.js
CHANGED
|
@@ -90,6 +90,8 @@ export function ChatMessage(handle) {
|
|
|
90
90
|
return () => {
|
|
91
91
|
const { role, label, attachments, children, size, time, actions, animate = true } = handle.props;
|
|
92
92
|
followMove();
|
|
93
|
+
if (role === 'system')
|
|
94
|
+
return (_jsx("article", { class: "rf-chat-message", "data-role": "system", "data-size": size, "data-animate": animate ? '' : undefined, "aria-label": label ?? 'System', mix: track, children: _jsxs("p", { class: "rf-chat-system", children: [handle.props.icon != null && (_jsx("span", { class: "rf-chat-system-icon", "aria-hidden": "true", children: handle.props.icon })), _jsx("span", { class: "rf-chat-system-text", children: children }), time && _jsx("span", { class: "rf-chat-time", children: time }), actions != null && _jsx("span", { class: "rf-chat-actions", children: actions })] }) }));
|
|
93
95
|
return (_jsxs("article", { class: "rf-chat-message", "data-role": role, "data-size": size, "data-animate": animate ? '' : undefined, "aria-label": label ?? (role === 'user' ? 'You' : 'Assistant'), mix: track, children: [attachments?.length ? (_jsx("ul", { class: "rf-chat-attachments", "aria-label": "Attachments", children: attachments.map((attachment, index) => (_jsxs("li", { class: "rf-chat-thumb", title: attachment.detail ? `${attachment.name} (${attachment.detail})` : undefined, children: [attachment.previewUrl ? (_jsx("img", { src: attachment.previewUrl, alt: attachment.name })) : (_jsx("span", { class: "rf-chat-thumb-glyph", role: "img", "aria-label": attachment.name, children: _jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: [_jsx("path", { d: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" }), _jsx("path", { d: "M14 3v5h5" })] }) })), attachment.url && _jsx("a", { href: attachment.url, "aria-label": attachment.name })] }, index))) })) : null, children != null && children !== '' && (_jsx("div", { class: "rf-chat-body", style: handle.props.transitionId
|
|
94
96
|
? { viewTransitionName: messageTransitionName(handle.props.transitionId) }
|
|
95
97
|
: undefined, children: children })), ((role === 'user' && time) || actions) && (_jsxs("div", { class: "rf-chat-meta", children: [role === 'user' && time && _jsx("span", { class: "rf-chat-time", children: time }), actions != null && _jsx("span", { class: "rf-chat-actions", children: actions })] }))] }));
|
package/dist/drawer.css
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
/* Drawer: a modal panel attached to one edge of the viewport.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/* Drawer: a modal panel attached to one edge of the viewport. The panel
|
|
2
|
+
and the backdrop share one motion, in and out and back from a drag: a
|
|
3
|
+
long ease that starts fast and settles gently, with no overshoot, so the
|
|
4
|
+
panel never lifts off its edge and the backdrop darkens as it arrives.
|
|
5
|
+
While dragged the panel follows --rf-drawer-drag, the distance toward its
|
|
6
|
+
edge, and the backdrop lightens with --rf-drawer-progress. A strip of
|
|
7
|
+
panel color past the edge covers the gap when a drag pulls it the other
|
|
8
|
+
way. */
|
|
7
9
|
.rf-drawer {
|
|
10
|
+
--rf-drawer-motion: 500ms cubic-bezier(0.32, 0.72, 0, 1);
|
|
8
11
|
--rf-drawer-bg: var(--rf-surface-5);
|
|
9
12
|
--rf-drawer-drag: 0px;
|
|
10
13
|
--rf-drawer-closed: 0 100%;
|
|
@@ -32,24 +35,12 @@
|
|
|
32
35
|
font: var(--rf-text-body) / var(--rf-leading-body) var(--rf-font);
|
|
33
36
|
translate: var(--rf-drawer-closed);
|
|
34
37
|
transition:
|
|
35
|
-
translate var(--rf-
|
|
36
|
-
overlay
|
|
37
|
-
display
|
|
38
|
+
translate var(--rf-drawer-motion),
|
|
39
|
+
overlay var(--rf-drawer-motion) allow-discrete,
|
|
40
|
+
display var(--rf-drawer-motion) allow-discrete;
|
|
38
41
|
}
|
|
39
42
|
.rf-drawer[open] {
|
|
40
43
|
translate: 0 var(--rf-drawer-drag);
|
|
41
|
-
transition:
|
|
42
|
-
translate var(--rf-spring-moderate),
|
|
43
|
-
overlay 160ms allow-discrete,
|
|
44
|
-
display 160ms allow-discrete;
|
|
45
|
-
}
|
|
46
|
-
@starting-style {
|
|
47
|
-
.rf-drawer[open] {
|
|
48
|
-
translate: var(--rf-drawer-closed);
|
|
49
|
-
}
|
|
50
|
-
.rf-drawer[open]::backdrop {
|
|
51
|
-
opacity: 0;
|
|
52
|
-
}
|
|
53
44
|
}
|
|
54
45
|
|
|
55
46
|
/* Top and bottom drawers keep their content in a readable column. */
|
|
@@ -100,23 +91,32 @@
|
|
|
100
91
|
background: rgb(0 0 0 / 40%);
|
|
101
92
|
opacity: 0;
|
|
102
93
|
transition:
|
|
103
|
-
opacity
|
|
104
|
-
overlay
|
|
105
|
-
display
|
|
94
|
+
opacity 500ms cubic-bezier(0.32, 0.72, 0, 1),
|
|
95
|
+
overlay 500ms cubic-bezier(0.32, 0.72, 0, 1) allow-discrete,
|
|
96
|
+
display 500ms cubic-bezier(0.32, 0.72, 0, 1) allow-discrete;
|
|
106
97
|
}
|
|
107
98
|
[data-theme='dark'] .rf-drawer::backdrop {
|
|
108
99
|
background: rgb(0 0 0 / 70%);
|
|
109
100
|
}
|
|
110
101
|
.rf-drawer[open]::backdrop {
|
|
111
|
-
opacity:
|
|
112
|
-
transition:
|
|
113
|
-
opacity var(--rf-spring-moderate),
|
|
114
|
-
overlay 160ms allow-discrete,
|
|
115
|
-
display 160ms allow-discrete;
|
|
102
|
+
opacity: 1;
|
|
116
103
|
}
|
|
117
104
|
.rf-drawer[data-dragging]::backdrop {
|
|
105
|
+
opacity: calc(1 - var(--rf-drawer-progress, 0));
|
|
118
106
|
transition: none;
|
|
119
107
|
}
|
|
108
|
+
/* Where the panel and backdrop start from as the drawer opens. Starting
|
|
109
|
+
styles cascade with the rest, so these follow the open rules above and
|
|
110
|
+
match the per-side ones in specificity, or those would win and the
|
|
111
|
+
drawer would appear without its slide. */
|
|
112
|
+
@starting-style {
|
|
113
|
+
.rf-drawer[data-side][open] {
|
|
114
|
+
translate: var(--rf-drawer-closed);
|
|
115
|
+
}
|
|
116
|
+
.rf-drawer[data-side][open]::backdrop {
|
|
117
|
+
opacity: 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
120
|
|
|
121
121
|
.rf-drawer-handle {
|
|
122
122
|
inline-size: 40px;
|
|
@@ -193,19 +193,15 @@
|
|
|
193
193
|
translate: none;
|
|
194
194
|
opacity: 0;
|
|
195
195
|
transition:
|
|
196
|
-
opacity var(--rf-
|
|
197
|
-
overlay
|
|
198
|
-
display
|
|
196
|
+
opacity var(--rf-drawer-motion),
|
|
197
|
+
overlay var(--rf-drawer-motion) allow-discrete,
|
|
198
|
+
display var(--rf-drawer-motion) allow-discrete;
|
|
199
199
|
}
|
|
200
200
|
.rf-drawer[open] {
|
|
201
201
|
opacity: 1;
|
|
202
|
-
transition:
|
|
203
|
-
opacity var(--rf-spring-moderate),
|
|
204
|
-
overlay 160ms allow-discrete,
|
|
205
|
-
display 160ms allow-discrete;
|
|
206
202
|
}
|
|
207
203
|
@starting-style {
|
|
208
|
-
.rf-drawer[open] {
|
|
204
|
+
.rf-drawer[data-side][open] {
|
|
209
205
|
translate: none;
|
|
210
206
|
opacity: 0;
|
|
211
207
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@rtzll/reflow/highlight`: Shiki behind one function, for CodeBlock.
|
|
3
|
+
*
|
|
4
|
+
* This entry is optional. It needs the `shiki` and `@shikijs/transformers`
|
|
5
|
+
* peer dependencies, and nothing else in Reflow imports it, so an app that
|
|
6
|
+
* never imports it never installs or loads Shiki.
|
|
7
|
+
*/
|
|
8
|
+
import { type BundledTheme, type ShikiTransformer, type ThemeRegistrationAny } from 'shiki';
|
|
9
|
+
import type { HighlightedCode } from './code-block.tsx';
|
|
10
|
+
export type { CodeLine, CodeToken, HighlightedCode } from './code-block.tsx';
|
|
11
|
+
type Theme = BundledTheme | ThemeRegistrationAny;
|
|
12
|
+
export interface HighlightOptions {
|
|
13
|
+
/** Any language Shiki bundles, or one of its aliases. Unknown languages render as plain text. Default text. */
|
|
14
|
+
lang?: string;
|
|
15
|
+
/** A Shiki theme, by name or definition. Defaults to Reflow's, which colours tokens with `--rf-code-token-*` variables. */
|
|
16
|
+
theme?: Theme;
|
|
17
|
+
/** A light and a dark theme; the block follows the page's color scheme between them. */
|
|
18
|
+
themes?: {
|
|
19
|
+
light: Theme;
|
|
20
|
+
dark: Theme;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Reads `// [!code highlight]`, `[!code ++]`, `[!code --]`, `[!code focus]`,
|
|
24
|
+
* `[!code error]`, `[!code warning]` and `[!code word:name]` comments into
|
|
25
|
+
* line and word marks, and removes them from the code. Default true.
|
|
26
|
+
*/
|
|
27
|
+
notation?: boolean;
|
|
28
|
+
/** More Shiki transformers, run after the notation ones. */
|
|
29
|
+
transformers?: ShikiTransformer[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Highlights code for CodeBlock. Call it where the code is known: in a route
|
|
33
|
+
* handler, so the page arrives highlighted and the browser loads nothing, or
|
|
34
|
+
* in the browser for code that arrives later, such as a streamed reply.
|
|
35
|
+
*/
|
|
36
|
+
export declare function highlight(code: string, options?: HighlightOptions): Promise<HighlightedCode>;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@rtzll/reflow/highlight`: Shiki behind one function, for CodeBlock.
|
|
3
|
+
*
|
|
4
|
+
* This entry is optional. It needs the `shiki` and `@shikijs/transformers`
|
|
5
|
+
* peer dependencies, and nothing else in Reflow imports it, so an app that
|
|
6
|
+
* never imports it never installs or loads Shiki.
|
|
7
|
+
*/
|
|
8
|
+
import { bundledLanguages, bundledLanguagesAlias, createCssVariablesTheme, createHighlighter, createJavaScriptRegexEngine, } from 'shiki';
|
|
9
|
+
import { transformerNotationDiff, transformerNotationErrorLevel, transformerNotationFocus, transformerNotationHighlight, transformerNotationWordHighlight, } from '@shikijs/transformers';
|
|
10
|
+
// Reflow's theme: every colour is a CSS variable, set in code-block.css for
|
|
11
|
+
// the light and dark themes, so highlighted code follows the page.
|
|
12
|
+
const reflowTheme = createCssVariablesTheme({
|
|
13
|
+
name: 'reflow',
|
|
14
|
+
variablePrefix: '--rf-code-',
|
|
15
|
+
fontStyle: true,
|
|
16
|
+
});
|
|
17
|
+
let shared;
|
|
18
|
+
// One highlighter for the process or page, with the JavaScript regex engine,
|
|
19
|
+
// which needs no WebAssembly. Languages and themes load as they are first used.
|
|
20
|
+
function highlighter() {
|
|
21
|
+
shared ??= createHighlighter({
|
|
22
|
+
themes: [reflowTheme],
|
|
23
|
+
langs: [],
|
|
24
|
+
engine: createJavaScriptRegexEngine({ forgiving: true }),
|
|
25
|
+
});
|
|
26
|
+
return shared;
|
|
27
|
+
}
|
|
28
|
+
function bundled(lang) {
|
|
29
|
+
return lang in bundledLanguages || lang in bundledLanguagesAlias;
|
|
30
|
+
}
|
|
31
|
+
function themeName(theme) {
|
|
32
|
+
return typeof theme === 'string' ? theme : (theme.name ?? 'custom');
|
|
33
|
+
}
|
|
34
|
+
function classes(node) {
|
|
35
|
+
const value = node.properties?.class ?? node.properties?.className;
|
|
36
|
+
return Array.isArray(value) ? value.join(' ') : typeof value === 'string' ? value : '';
|
|
37
|
+
}
|
|
38
|
+
// Flattens a line into runs of text, each with the innermost style and
|
|
39
|
+
// every class around it, such as a token inside a highlighted word.
|
|
40
|
+
function tokens(node, style = '', classList = []) {
|
|
41
|
+
if (node.type === 'text') {
|
|
42
|
+
if (!node.value)
|
|
43
|
+
return [];
|
|
44
|
+
const token = { content: node.value };
|
|
45
|
+
if (style)
|
|
46
|
+
token.style = style;
|
|
47
|
+
if (classList.length)
|
|
48
|
+
token.class = classList.join(' ');
|
|
49
|
+
return [token];
|
|
50
|
+
}
|
|
51
|
+
const own = typeof node.properties?.style === 'string' ? node.properties.style : '';
|
|
52
|
+
const name = classes(node);
|
|
53
|
+
const nested = name ? [...classList, name] : classList;
|
|
54
|
+
return (node.children ?? []).flatMap((child) => tokens(child, own || style, nested));
|
|
55
|
+
}
|
|
56
|
+
function trimEnd(list) {
|
|
57
|
+
while (list.length) {
|
|
58
|
+
const last = list[list.length - 1];
|
|
59
|
+
last.content = last.content.replace(/[ \t]+$/, '');
|
|
60
|
+
if (last.content)
|
|
61
|
+
return;
|
|
62
|
+
list.pop();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Highlights code for CodeBlock. Call it where the code is known: in a route
|
|
67
|
+
* handler, so the page arrives highlighted and the browser loads nothing, or
|
|
68
|
+
* in the browser for code that arrives later, such as a streamed reply.
|
|
69
|
+
*/
|
|
70
|
+
export async function highlight(code, options = {}) {
|
|
71
|
+
const instance = await highlighter();
|
|
72
|
+
const requested = options.lang ?? 'text';
|
|
73
|
+
const lang = bundled(requested) ? requested : 'text';
|
|
74
|
+
if (lang !== 'text' && !instance.getLoadedLanguages().includes(lang))
|
|
75
|
+
await instance.loadLanguage(lang);
|
|
76
|
+
const themes = options.themes ? [options.themes.light, options.themes.dark] : [options.theme];
|
|
77
|
+
for (const theme of themes)
|
|
78
|
+
if (theme && !instance.getLoadedThemes().includes(themeName(theme)))
|
|
79
|
+
await instance.loadTheme(theme);
|
|
80
|
+
const transformers = [
|
|
81
|
+
...(options.notation === false
|
|
82
|
+
? []
|
|
83
|
+
: [
|
|
84
|
+
transformerNotationHighlight(),
|
|
85
|
+
transformerNotationDiff(),
|
|
86
|
+
transformerNotationFocus(),
|
|
87
|
+
transformerNotationErrorLevel(),
|
|
88
|
+
transformerNotationWordHighlight(),
|
|
89
|
+
]),
|
|
90
|
+
...(options.transformers ?? []),
|
|
91
|
+
];
|
|
92
|
+
const root = instance.codeToHast(code, options.themes
|
|
93
|
+
? {
|
|
94
|
+
lang,
|
|
95
|
+
themes: {
|
|
96
|
+
light: themeName(options.themes.light),
|
|
97
|
+
dark: themeName(options.themes.dark),
|
|
98
|
+
},
|
|
99
|
+
defaultColor: false,
|
|
100
|
+
transformers,
|
|
101
|
+
}
|
|
102
|
+
: { lang, theme: options.theme ? themeName(options.theme) : 'reflow', transformers });
|
|
103
|
+
const pre = root.children?.find((node) => node.tagName === 'pre');
|
|
104
|
+
const body = pre?.children?.find((node) => node.tagName === 'code');
|
|
105
|
+
const lines = (body?.children ?? [])
|
|
106
|
+
.filter((node) => node.type === 'element')
|
|
107
|
+
.map((node) => {
|
|
108
|
+
const mark = classes(node)
|
|
109
|
+
.split(/\s+/)
|
|
110
|
+
.filter((name) => name && name !== 'line')
|
|
111
|
+
.join(' ');
|
|
112
|
+
const line = { tokens: tokens({ ...node, properties: {} }) };
|
|
113
|
+
// Removing a notation comment leaves the space before it.
|
|
114
|
+
if (options.notation !== false)
|
|
115
|
+
trimEnd(line.tokens);
|
|
116
|
+
if (mark)
|
|
117
|
+
line.class = mark;
|
|
118
|
+
return line;
|
|
119
|
+
});
|
|
120
|
+
const flags = classes(pre ?? { type: 'element' })
|
|
121
|
+
.split(/\s+/)
|
|
122
|
+
.filter((name) => name.startsWith('has-'));
|
|
123
|
+
const style = typeof pre?.properties?.style === 'string' ? pre.properties.style : undefined;
|
|
124
|
+
const result = {
|
|
125
|
+
lang: requested === 'text' || lang === 'text' ? 'text' : requested,
|
|
126
|
+
code: lines.map((line) => line.tokens.map((token) => token.content).join('')).join('\n'),
|
|
127
|
+
lines,
|
|
128
|
+
flags,
|
|
129
|
+
};
|
|
130
|
+
// Reflow's own theme takes its colours from CSS; others bring theirs inline.
|
|
131
|
+
if (style && (options.theme || options.themes))
|
|
132
|
+
result.style = style;
|
|
133
|
+
return result;
|
|
134
|
+
}
|
package/dist/hover-card.d.ts
CHANGED
|
@@ -28,5 +28,9 @@ export interface HoverCardProps {
|
|
|
28
28
|
* follows it, and the card never takes focus or locks scrolling. The pointer
|
|
29
29
|
* can cross into the card and use its links; it closes once the pointer has
|
|
30
30
|
* left both, or on Escape. It shares Popover's surface and motion.
|
|
31
|
+
*
|
|
32
|
+
* The card is a span, so a trigger can sit inside a paragraph. Keep its
|
|
33
|
+
* content to phrasing elements there, such as span and a, since a div or a
|
|
34
|
+
* list would end the paragraph when the browser parses server-rendered HTML.
|
|
31
35
|
*/
|
|
32
36
|
export declare function HoverCard(handle: Handle<HoverCardProps>): () => import("remix/component").RemixElement;
|
package/dist/hover-card.js
CHANGED
|
@@ -8,6 +8,10 @@ import { anchor } from '@remix-run/ui/anchor';
|
|
|
8
8
|
* follows it, and the card never takes focus or locks scrolling. The pointer
|
|
9
9
|
* can cross into the card and use its links; it closes once the pointer has
|
|
10
10
|
* left both, or on Escape. It shares Popover's surface and motion.
|
|
11
|
+
*
|
|
12
|
+
* The card is a span, so a trigger can sit inside a paragraph. Keep its
|
|
13
|
+
* content to phrasing elements there, such as span and a, since a div or a
|
|
14
|
+
* list would end the paragraph when the browser parses server-rendered HTML.
|
|
11
15
|
*/
|
|
12
16
|
export function HoverCard(handle) {
|
|
13
17
|
let trigger = null;
|
|
@@ -114,6 +118,6 @@ export function HoverCard(handle) {
|
|
|
114
118
|
});
|
|
115
119
|
return () => {
|
|
116
120
|
handle.queueTask(sync);
|
|
117
|
-
return (_jsxs(_Fragment, { children: [handle.props.renderTrigger({ mix: triggerMix }), _jsx("
|
|
121
|
+
return (_jsxs(_Fragment, { children: [handle.props.renderTrigger({ mix: triggerMix }), _jsx("span", { class: "rf-menu-surface rf-popover-surface rf-hover-card", popover: "manual", "data-density": handle.props.size, mix: cardMix, children: handle.props.children })] }));
|
|
118
122
|
};
|
|
119
123
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ export * from './popover.tsx';
|
|
|
15
15
|
export * from './hover-card.tsx';
|
|
16
16
|
export * from './toaster.tsx';
|
|
17
17
|
export * from './drawer.tsx';
|
|
18
|
+
export * from './code-block.tsx';
|
|
19
|
+
export * from './citation.tsx';
|
|
20
|
+
export * from './avatar.tsx';
|
|
21
|
+
export * from './chat-layout.tsx';
|
|
18
22
|
export * from './systems.ts';
|
|
19
23
|
export * from './queued-stack.tsx';
|
|
20
24
|
export * from './scroll-area.tsx';
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,10 @@ export * from './popover.js';
|
|
|
15
15
|
export * from './hover-card.js';
|
|
16
16
|
export * from './toaster.js';
|
|
17
17
|
export * from './drawer.js';
|
|
18
|
+
export * from './code-block.js';
|
|
19
|
+
export * from './citation.js';
|
|
20
|
+
export * from './avatar.js';
|
|
21
|
+
export * from './chat-layout.js';
|
|
18
22
|
export * from './systems.js';
|
|
19
23
|
export * from './queued-stack.js';
|
|
20
24
|
export * from './scroll-area.js';
|
package/dist/styles.css
CHANGED
package/dist/toaster.js
CHANGED
|
@@ -70,12 +70,13 @@ export const toast = Object.assign((title, options) => upsert(title, 'default',
|
|
|
70
70
|
info: (title, options) => upsert(title, 'info', options),
|
|
71
71
|
warning: (title, options) => upsert(title, 'warning', options),
|
|
72
72
|
error: (title, options) => upsert(title, 'error', options),
|
|
73
|
-
loading
|
|
73
|
+
// A loading toast stays without a duration of its own: the close timer
|
|
74
|
+
// skips loading toasts, so it starts once the toast settles.
|
|
75
|
+
loading: (title, options) => upsert(title, 'loading', options),
|
|
74
76
|
promise(promise, messages, options = {}) {
|
|
75
77
|
const id = upsert(messages.loading, 'loading', {
|
|
76
78
|
description: messages.description,
|
|
77
79
|
...options,
|
|
78
|
-
duration: Infinity,
|
|
79
80
|
});
|
|
80
81
|
const settle = (status, title) => {
|
|
81
82
|
// A toast closed while it waited stays closed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rtzll/reflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -13,13 +13,29 @@
|
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
14
|
"default": "./dist/index.js"
|
|
15
15
|
},
|
|
16
|
+
"./highlight": {
|
|
17
|
+
"types": "./dist/highlight.d.ts",
|
|
18
|
+
"default": "./dist/highlight.js"
|
|
19
|
+
},
|
|
16
20
|
"./styles.css": "./dist/styles.css"
|
|
17
21
|
},
|
|
18
22
|
"peerDependencies": {
|
|
19
|
-
"
|
|
23
|
+
"@shikijs/transformers": "^4.5.0",
|
|
24
|
+
"remix": "3.2.0",
|
|
25
|
+
"shiki": "^4.5.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"@shikijs/transformers": {
|
|
29
|
+
"optional": true
|
|
30
|
+
},
|
|
31
|
+
"shiki": {
|
|
32
|
+
"optional": true
|
|
33
|
+
}
|
|
20
34
|
},
|
|
21
35
|
"devDependencies": {
|
|
22
|
-
"
|
|
36
|
+
"@shikijs/transformers": "4.5.0",
|
|
37
|
+
"remix": "3.2.0",
|
|
38
|
+
"shiki": "4.5.0"
|
|
23
39
|
},
|
|
24
40
|
"dependencies": {
|
|
25
41
|
"@remix-run/ui": "0.13.1"
|