@k2b/ui 0.14.0 → 0.16.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 +5 -0
- package/dist/base.css +1097 -0
- package/dist/browser/chat/ChatPrimitives.js +19 -16
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/ChatTimeline.js +110 -87
- package/dist/browser/chat/ChatTimeline.js.map +1 -1
- package/dist/browser/content/FileGrid.js +28 -8
- package/dist/browser/content/FileGrid.js.map +1 -1
- package/dist/browser/content/MarkdownView.js +11 -5
- package/dist/browser/content/MarkdownView.js.map +1 -1
- package/dist/browser/content/MessageRow.js +1250 -0
- package/dist/browser/content/MessageRow.js.map +1 -0
- package/dist/browser/content/StructuredDataPreview.js +4 -1
- package/dist/browser/content/StructuredDataPreview.js.map +1 -1
- package/dist/browser/content/VirtualFeed.js +1127 -0
- package/dist/browser/content/VirtualFeed.js.map +1 -0
- package/dist/browser/content/collection-selection.js +27 -11
- package/dist/browser/content/collection-selection.js.map +1 -1
- package/dist/browser/content/index.js +2 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/InstallGuide.js +199 -145
- package/dist/browser/feedback/InstallGuide.js.map +1 -1
- package/dist/browser/feedback/install.js +8 -4
- package/dist/browser/feedback/install.js.map +1 -1
- package/dist/browser/inputs/QrScanner.js +101 -21
- package/dist/browser/inputs/QrScanner.js.map +1 -1
- package/dist/browser/intl/messages.js +86 -0
- package/dist/browser/intl/messages.js.map +1 -1
- package/dist/browser/surfaces/Avatar.js +33 -17
- package/dist/browser/surfaces/Avatar.js.map +1 -1
- package/dist/ssr/chat/ChatPrimitives.js +2 -2
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/ChatTimeline.js +110 -87
- package/dist/ssr/chat/ChatTimeline.js.map +1 -1
- package/dist/ssr/content/FileGrid.js +17 -3
- package/dist/ssr/content/FileGrid.js.map +1 -1
- package/dist/ssr/content/MarkdownView.js +11 -5
- package/dist/ssr/content/MarkdownView.js.map +1 -1
- package/dist/ssr/content/MessageRow.js +796 -0
- package/dist/ssr/content/MessageRow.js.map +1 -0
- package/dist/ssr/content/StructuredDataPreview.js +1 -1
- package/dist/ssr/content/StructuredDataPreview.js.map +1 -1
- package/dist/ssr/content/VirtualFeed.js +989 -0
- package/dist/ssr/content/VirtualFeed.js.map +1 -0
- package/dist/ssr/content/collection-selection.js +27 -11
- package/dist/ssr/content/collection-selection.js.map +1 -1
- package/dist/ssr/content/index.js +2 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/InstallGuide.js +150 -98
- package/dist/ssr/feedback/InstallGuide.js.map +1 -1
- package/dist/ssr/feedback/install.js +8 -4
- package/dist/ssr/feedback/install.js.map +1 -1
- package/dist/ssr/inputs/QrScanner.js +101 -21
- package/dist/ssr/inputs/QrScanner.js.map +1 -1
- package/dist/ssr/intl/messages.js +86 -0
- package/dist/ssr/intl/messages.js.map +1 -1
- package/dist/ssr/surfaces/Avatar.js +14 -1
- package/dist/ssr/surfaces/Avatar.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/chat/ChatPrimitives.d.ts +2 -0
- package/dist/types/chat/ChatTimeline.d.ts +2 -0
- package/dist/types/content/FileGrid.d.ts +6 -1
- package/dist/types/content/MarkdownView.d.ts +8 -0
- package/dist/types/content/MessageRow.d.ts +168 -0
- package/dist/types/content/VirtualFeed.d.ts +81 -0
- package/dist/types/content/collection-selection.d.ts +15 -1
- package/dist/types/content/index.d.ts +4 -0
- package/dist/types/feedback/InstallGuide.d.ts +5 -3
- package/dist/types/feedback/install.d.ts +4 -3
- package/dist/types/inputs/QrScanner.d.ts +10 -2
- package/dist/types/intl/messages.d.ts +43 -0
- package/package.json +3 -1
|
@@ -16,6 +16,8 @@ export type ChatMessageProps = {
|
|
|
16
16
|
};
|
|
17
17
|
export type ChatActivityProps = {
|
|
18
18
|
label: string;
|
|
19
|
+
/** Spelled-out name for an expandable row whose visible text abbreviates, such as durations. */
|
|
20
|
+
ariaLabel?: string;
|
|
19
21
|
description?: string;
|
|
20
22
|
icon?: string;
|
|
21
23
|
/** Optional host-owned leading visual rendered instead of the icon. */
|
|
@@ -2,6 +2,7 @@ import { type JSX } from "solid-js";
|
|
|
2
2
|
import type { ChatAction, ChatActivityTone, ChatAttachment, ChatMessageStatus, ChatRole } from "./types";
|
|
3
3
|
export type ChatMessageItem = {
|
|
4
4
|
kind: "message";
|
|
5
|
+
/** Unique within the timeline. A record with a known id updates its row in place instead of replacing it. */
|
|
5
6
|
id: string;
|
|
6
7
|
role: ChatRole;
|
|
7
8
|
content?: JSX.Element;
|
|
@@ -17,6 +18,7 @@ export type ChatMessageItem = {
|
|
|
17
18
|
};
|
|
18
19
|
export type ChatActivityItem = {
|
|
19
20
|
kind: "activity";
|
|
21
|
+
/** Unique within the timeline. A record with a known id updates its row in place instead of replacing it. */
|
|
20
22
|
id: string;
|
|
21
23
|
label: string;
|
|
22
24
|
description?: string;
|
|
@@ -6,6 +6,8 @@ export type FileGridProps<T> = {
|
|
|
6
6
|
selection: CollectionSelection;
|
|
7
7
|
label: string;
|
|
8
8
|
size?: "sm" | "md" | "lg";
|
|
9
|
+
/** `list` shows one compact row per item: preview, name, and meta beside each other. Defaults to `grid`. */
|
|
10
|
+
layout?: "grid" | "list";
|
|
9
11
|
renderPreview: (row: T) => JSX.Element;
|
|
10
12
|
renderLabel: (row: T) => JSX.Element;
|
|
11
13
|
renderMeta?: (row: T) => JSX.Element;
|
|
@@ -17,5 +19,8 @@ export type FileGridProps<T> = {
|
|
|
17
19
|
itemProps?: (row: T) => JSX.HTMLAttributes<HTMLDivElement>;
|
|
18
20
|
class?: string;
|
|
19
21
|
};
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* File presentation only; the host owns data, menus, leases and permissions. Items the selection marks with
|
|
24
|
+
* `isDisabled` stay reachable by keyboard but cannot be selected or opened; say why in `renderMeta`.
|
|
25
|
+
*/
|
|
21
26
|
export declare function FileGrid<T>(props: FileGridProps<T>): JSX.Element;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Marked, Renderer } from "marked";
|
|
1
2
|
type CommonProps = MarkdownRenderOptions & {
|
|
2
3
|
/** Optional additional CSS classes */
|
|
3
4
|
class?: string;
|
|
@@ -29,7 +30,14 @@ export type MarkdownRenderOptions = {
|
|
|
29
30
|
/** Locale for the screen-reader names of untitled info blocks. `MarkdownView` passes the inherited render locale. */
|
|
30
31
|
locale?: string;
|
|
31
32
|
};
|
|
33
|
+
export declare const escapeHtml: (value: string) => string;
|
|
34
|
+
export declare const createSafeRenderer: (options?: MarkdownRenderOptions) => Renderer;
|
|
32
35
|
export declare const renderSafeMarkdown: (markdown: string, options?: MarkdownRenderOptions) => string;
|
|
36
|
+
/**
|
|
37
|
+
* Internal to the package: the Markdown grammar of `renderSafeMarkdown`, for a component that renders with an adjusted
|
|
38
|
+
* safe renderer or reads the tokens, as `MessageRow` does.
|
|
39
|
+
*/
|
|
40
|
+
export declare const createSafeMarked: (locale?: string) => Marked;
|
|
33
41
|
/**
|
|
34
42
|
* Markdown View Component (SSR)
|
|
35
43
|
*
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { type JSX } from "solid-js";
|
|
2
|
+
export type MessageRowAuthor = {
|
|
3
|
+
/** Display name, shown at the start of a group and read before every message. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Picture URL. Without one, the avatar shows initials on the author's tint. */
|
|
6
|
+
avatar?: string | null;
|
|
7
|
+
/** Icon class shown instead of initials, for example for an automated author. */
|
|
8
|
+
icon?: string;
|
|
9
|
+
};
|
|
10
|
+
export type MessageRowStatus = "pending" | "sent" | "failed";
|
|
11
|
+
export type MessageRowAction = {
|
|
12
|
+
id: string;
|
|
13
|
+
/** Accessible name and tooltip. */
|
|
14
|
+
label: string;
|
|
15
|
+
/** Icon class, for example `ti ti-arrow-back-up`. */
|
|
16
|
+
icon: string;
|
|
17
|
+
onSelect: () => void;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type MessageRowQuote = {
|
|
21
|
+
/** Name of the quoted message's author. */
|
|
22
|
+
author: string;
|
|
23
|
+
/** Plain text of the quoted message. It shows at most two lines. */
|
|
24
|
+
text: string;
|
|
25
|
+
/** Opens the quoted message, for example by scrolling to it. Without it, the quote is not a control. */
|
|
26
|
+
onSelect?: () => void;
|
|
27
|
+
};
|
|
28
|
+
export type MessageRowReaction = {
|
|
29
|
+
/** Stable identity of the reaction, passed to `onToggleReaction`. */
|
|
30
|
+
key: string;
|
|
31
|
+
emoji: string;
|
|
32
|
+
count: number;
|
|
33
|
+
/** The reader reacted this way; the chip shows pressed. */
|
|
34
|
+
own?: boolean;
|
|
35
|
+
/** Who reacted, for example "Nora, Tobias". Read by screen readers and shown as a tooltip. */
|
|
36
|
+
label?: string;
|
|
37
|
+
};
|
|
38
|
+
export type MessageRowThread = {
|
|
39
|
+
/** Number of replies. */
|
|
40
|
+
count: number;
|
|
41
|
+
/** People who replied, most recent first; the bar shows up to three. */
|
|
42
|
+
participants?: readonly MessageRowAuthor[];
|
|
43
|
+
/** Visible time of the last reply, formatted by the caller. */
|
|
44
|
+
lastReply?: string;
|
|
45
|
+
lastReplyDateTime?: string | Date;
|
|
46
|
+
onOpen: () => void;
|
|
47
|
+
};
|
|
48
|
+
type MessageRowAttachmentTarget = {
|
|
49
|
+
/** Opens the attachment, for example in a lightbox. Takes precedence over `href`. */
|
|
50
|
+
onOpen?: () => void;
|
|
51
|
+
/** Opens the attachment in a new tab. Absolute `https` or `http`, or relative. */
|
|
52
|
+
href?: string;
|
|
53
|
+
};
|
|
54
|
+
export type MessageRowMedia = MessageRowAttachmentTarget & {
|
|
55
|
+
kind: "image" | "video";
|
|
56
|
+
/** The image, or the poster frame of a video. Absolute `https` or `http`, relative, `blob`, or `data:image/`. */
|
|
57
|
+
src: string;
|
|
58
|
+
/** Describes the image or video for people who cannot see it. */
|
|
59
|
+
alt: string;
|
|
60
|
+
/** Stored pixel size. The row reserves the area from it, so nothing moves when the image loads. */
|
|
61
|
+
width: number;
|
|
62
|
+
height: number;
|
|
63
|
+
/** Visible length of a video, for example "0:42". */
|
|
64
|
+
duration?: string;
|
|
65
|
+
};
|
|
66
|
+
export type MessageRowFile = MessageRowAttachmentTarget & {
|
|
67
|
+
kind: "file";
|
|
68
|
+
name: string;
|
|
69
|
+
/** Second line, for example "PDF · 412 KB". */
|
|
70
|
+
detail?: string;
|
|
71
|
+
/** Media type, used with the name to choose the icon. */
|
|
72
|
+
mediaType?: string;
|
|
73
|
+
/** Icon class instead of the one chosen from the name. */
|
|
74
|
+
icon?: string;
|
|
75
|
+
};
|
|
76
|
+
export type MessageRowAttachment = MessageRowMedia | MessageRowFile;
|
|
77
|
+
export type MessageRowProgress = {
|
|
78
|
+
/** What is happening, for example "Writing" or "Searching the files". */
|
|
79
|
+
status: string;
|
|
80
|
+
/** Called by "Stop". */
|
|
81
|
+
onStop?: () => void;
|
|
82
|
+
};
|
|
83
|
+
export type MessageRowProps = {
|
|
84
|
+
author: MessageRowAuthor;
|
|
85
|
+
/** Message text as Markdown. Raw HTML shows as text; links must be absolute and use `https`, `http`, or `mailto`. */
|
|
86
|
+
text: string;
|
|
87
|
+
/** Visible time, formatted by the caller, so server and browser render the same text. */
|
|
88
|
+
time: string;
|
|
89
|
+
/** Machine-readable time for the `<time>` element. */
|
|
90
|
+
dateTime?: string | Date;
|
|
91
|
+
/** The reader's own message: on the right in the accent tint, without avatar or name. */
|
|
92
|
+
own?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Starts a group with avatar, name, badge, and time. A continuation shows only its text; screen readers still hear
|
|
95
|
+
* the author and time. Defaults to true; `startsMessageGroup` decides it from the previous message.
|
|
96
|
+
*/
|
|
97
|
+
groupStart?: boolean;
|
|
98
|
+
/** Shown next to the name at the start of a group, for example the kind of account. */
|
|
99
|
+
badge?: JSX.Element;
|
|
100
|
+
/** Send state. Sets a line of fixed height below the message: a clock, a check, or "Not sent" with "Retry". */
|
|
101
|
+
status?: MessageRowStatus;
|
|
102
|
+
/** Text shown in that line instead of the check once someone has read the message, for example "Read by Nora". */
|
|
103
|
+
receipt?: string;
|
|
104
|
+
/** Called by "Retry" while `status` is `"failed"`. */
|
|
105
|
+
onRetry?: () => void;
|
|
106
|
+
/** Shown as a toolbar over the message while it is hovered or focused. It never moves the layout. */
|
|
107
|
+
actions?: readonly MessageRowAction[];
|
|
108
|
+
/** The message this one answers, shown above it. */
|
|
109
|
+
quote?: MessageRowQuote;
|
|
110
|
+
/** Marks the message as forwarded from somewhere else. */
|
|
111
|
+
forwarded?: boolean;
|
|
112
|
+
/** Marks the message as edited after it was sent. */
|
|
113
|
+
edited?: boolean;
|
|
114
|
+
/** Shows "This message was deleted" instead of the text, quote, attachments, previews, and reactions. */
|
|
115
|
+
deleted?: boolean;
|
|
116
|
+
/** Images and videos in a grid with areas reserved from their stored size, then files as chips. */
|
|
117
|
+
attachments?: readonly MessageRowAttachment[];
|
|
118
|
+
/** A preview of a link in the text, supplied with its final height. */
|
|
119
|
+
linkPreview?: JSX.Element;
|
|
120
|
+
/** A card for an element the message refers to, such as a task or a document, supplied with its final height. */
|
|
121
|
+
card?: JSX.Element;
|
|
122
|
+
/**
|
|
123
|
+
* Reactions in a bar of fixed height. The bar shows whenever this is set, even to an empty list, so chips that come
|
|
124
|
+
* and go never change the row. Only setting it where it was unset adds a line, so pass it on own messages and on
|
|
125
|
+
* messages that have or had reactions, and leave it out on others' messages that never had one.
|
|
126
|
+
*/
|
|
127
|
+
reactions?: readonly MessageRowReaction[];
|
|
128
|
+
/** Called with a reaction's `key` when the reader presses its chip. Without it, the chips are not controls. */
|
|
129
|
+
onToggleReaction?: (key: string) => void;
|
|
130
|
+
/** Called by "Add reaction" in the reaction bar, with the button to anchor a picker to. */
|
|
131
|
+
onAddReaction?: (anchor: HTMLElement) => void;
|
|
132
|
+
/** A bar of fixed height that opens the replies to this message. */
|
|
133
|
+
thread?: MessageRowThread;
|
|
134
|
+
/** The message is still being written, by a person or an automated author alike: a status line with "Stop". */
|
|
135
|
+
progress?: MessageRowProgress;
|
|
136
|
+
class?: string;
|
|
137
|
+
};
|
|
138
|
+
export type MessageSystemRowProps = {
|
|
139
|
+
/** What happened, for example "Nora added Tobias". */
|
|
140
|
+
children: JSX.Element;
|
|
141
|
+
/** Visible time, formatted by the caller. */
|
|
142
|
+
time?: string;
|
|
143
|
+
dateTime?: string | Date;
|
|
144
|
+
/** Icon class shown before the text. */
|
|
145
|
+
icon?: string;
|
|
146
|
+
class?: string;
|
|
147
|
+
};
|
|
148
|
+
export type MessageGroupEntry = {
|
|
149
|
+
/** Stable identity of the author. */
|
|
150
|
+
author: string;
|
|
151
|
+
at: Date | number | string;
|
|
152
|
+
/** System rows never belong to a group. */
|
|
153
|
+
system?: boolean;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Whether a message starts a new group: there is no previous message, either is a system row, the author changes, or
|
|
157
|
+
* more than five minutes passed. Also start a group where you show a separator such as a new day.
|
|
158
|
+
*/
|
|
159
|
+
export declare const startsMessageGroup: (entry: MessageGroupEntry, previous?: MessageGroupEntry | null) => boolean;
|
|
160
|
+
/**
|
|
161
|
+
* One message in a conversation with many people: own messages on the right, others on the left with avatar, name,
|
|
162
|
+
* and time at the start of a group. Every part has its final height when the row mounts, so a virtualized list such
|
|
163
|
+
* as `VirtualFeed` keeps its positions.
|
|
164
|
+
*/
|
|
165
|
+
export declare function MessageRow(props: MessageRowProps): JSX.Element;
|
|
166
|
+
/** A quiet, centered line for something that happened in the conversation, such as a person joining. */
|
|
167
|
+
export declare function MessageSystemRow(props: MessageSystemRowProps): JSX.Element;
|
|
168
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { type Accessor, type JSX } from "solid-js";
|
|
2
|
+
export type VirtualFeedScrollOptions = {
|
|
3
|
+
/** Where the item lands in the visible area. Defaults to `"center"`. */
|
|
4
|
+
align?: "start" | "center";
|
|
5
|
+
/** Tints the item briefly so the reader finds it. */
|
|
6
|
+
highlight?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type VirtualFeedController = {
|
|
9
|
+
/**
|
|
10
|
+
* Scrolls to a loaded item, also when the reader's scroll still coasts. Returns false when no loaded item has this
|
|
11
|
+
* key, so the caller can load around it first.
|
|
12
|
+
*/
|
|
13
|
+
scrollToKey: (key: string, options?: VirtualFeedScrollOptions) => boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Follows the end again, also when the reader's scroll still coasts. When newer items exist but are not loaded, it
|
|
16
|
+
* asks `onLoadNewest` for them first.
|
|
17
|
+
*/
|
|
18
|
+
scrollToEnd: () => void;
|
|
19
|
+
/** Whether the reader is at the end and new items keep the feed there. */
|
|
20
|
+
isAtEnd: () => boolean;
|
|
21
|
+
};
|
|
22
|
+
export type VirtualFeedProps<T> = {
|
|
23
|
+
/** Loaded items, oldest first. Replace the array to add, remove, or change items. */
|
|
24
|
+
items: readonly T[];
|
|
25
|
+
/** Stable, unique identity of an item across updates. */
|
|
26
|
+
getKey: (item: T) => string;
|
|
27
|
+
/** Height in px before the item was measured. Close estimates mean fewer corrections while scrolling. */
|
|
28
|
+
estimateSize: (item: T) => number;
|
|
29
|
+
/** Content of one item, created once per item object as with Solid's `For`. `index` is its position in `items`. */
|
|
30
|
+
children: (item: T, index: Accessor<number>) => JSX.Element;
|
|
31
|
+
/** Accessible name of the feed. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Accessible name of one item, for example its author and time. */
|
|
34
|
+
itemLabel?: (item: T) => string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Label shown above an item, for example when the day changes. Return nothing for no separator. While `hasOlder` is
|
|
37
|
+
* set, the first loaded item has no known predecessor and gets none.
|
|
38
|
+
*/
|
|
39
|
+
separator?: (item: T, previous: T | undefined) => JSX.Element;
|
|
40
|
+
/** Key of the first item the reader has not seen; a marker appears above it. */
|
|
41
|
+
markerKey?: string | null;
|
|
42
|
+
/** Text of that marker. Defaults to "New". */
|
|
43
|
+
markerLabel?: string;
|
|
44
|
+
/** Older items exist that `items` does not contain yet. */
|
|
45
|
+
hasOlder?: boolean;
|
|
46
|
+
/** Newer items exist that `items` does not contain yet. */
|
|
47
|
+
hasNewer?: boolean;
|
|
48
|
+
/** Called near the start of the loaded items while `hasOlder` is true. Prepend the next older page to `items`. */
|
|
49
|
+
onLoadOlder?: () => unknown;
|
|
50
|
+
/** Called near the end of the loaded items while `hasNewer` is true. Append the next newer page to `items`. */
|
|
51
|
+
onLoadNewer?: () => unknown;
|
|
52
|
+
/** Called by "Jump to latest" while `hasNewer` is true. Replace `items` with the newest page. */
|
|
53
|
+
onLoadNewest?: () => unknown;
|
|
54
|
+
/** Marks the feed as busy for assistive technology, for example during the first load. */
|
|
55
|
+
busy?: boolean;
|
|
56
|
+
/** Number of items in the whole feed when known. */
|
|
57
|
+
totalCount?: number;
|
|
58
|
+
/** One-based position of `items[0]` in the whole feed when known. */
|
|
59
|
+
firstPosition?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Count shown on "Jump to latest". Defaults to the new items added while the reader was away from the end, which
|
|
62
|
+
* excludes pages of older history loaded toward the end.
|
|
63
|
+
*/
|
|
64
|
+
newCount?: number;
|
|
65
|
+
/** Text announced for new items added at the end, bundled per second. Return nothing to stay silent. */
|
|
66
|
+
announce?: (added: readonly T[]) => string | undefined;
|
|
67
|
+
/** Called when the reader reaches or leaves the end. */
|
|
68
|
+
onEndChange?: (atEnd: boolean) => void;
|
|
69
|
+
/** Receives the controller once the feed is mounted. */
|
|
70
|
+
controller?: (controller: VirtualFeedController) => void;
|
|
71
|
+
/** Shown while `items` is empty. */
|
|
72
|
+
empty?: JSX.Element;
|
|
73
|
+
class?: string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* A virtualized feed of items with variable heights that grows at both ends and keeps the reading position: it stays
|
|
77
|
+
* at the end while the reader is there, and otherwise keeps the item in view where it is, whatever loads, grows, or
|
|
78
|
+
* resizes around it.
|
|
79
|
+
*/
|
|
80
|
+
export declare function VirtualFeed<T>(props: VirtualFeedProps<T>): JSX.Element;
|
|
81
|
+
export default VirtualFeed;
|
|
@@ -4,14 +4,28 @@ export type SelectionModifiers = {
|
|
|
4
4
|
metaKey?: boolean;
|
|
5
5
|
};
|
|
6
6
|
export type CollectionSelection = ReturnType<typeof createCollectionSelection>;
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* One selection and focus model shared by alternate presentations of a collection.
|
|
9
|
+
*
|
|
10
|
+
* `ids` is the collection in display order. `isDisabled` marks items that stay in focus order, so the keyboard and
|
|
11
|
+
* screen readers still reach them, but can never be selected. `multiple: false` keeps at most one ID selected: a
|
|
12
|
+
* click, toggle, or arrow key selects only that item, and ranges and select-all do nothing.
|
|
13
|
+
*
|
|
14
|
+
* `checklist: true` suits choosing on touch screens: a plain click or tap toggles one item, and arrow keys only move
|
|
15
|
+
* focus. Space still toggles; Shift-click still selects a range.
|
|
16
|
+
*/
|
|
8
17
|
export declare function createCollectionSelection(options: {
|
|
9
18
|
ids: () => readonly string[];
|
|
19
|
+
isDisabled?: (id: string) => boolean;
|
|
10
20
|
initial?: readonly string[];
|
|
11
21
|
onChange?: (ids: readonly string[]) => void;
|
|
22
|
+
multiple?: boolean;
|
|
23
|
+
checklist?: boolean;
|
|
12
24
|
}): {
|
|
25
|
+
multiple: boolean;
|
|
13
26
|
selected: import("solid-js").Accessor<ReadonlySet<string>>;
|
|
14
27
|
focused: import("solid-js").Accessor<string | null>;
|
|
28
|
+
isDisabled: (id: string) => boolean;
|
|
15
29
|
select: (id: string, modifiers?: SelectionModifiers) => void;
|
|
16
30
|
toggle: (id: string) => void;
|
|
17
31
|
replace: (ids: readonly string[]) => void;
|
|
@@ -31,6 +31,8 @@ export { default as Lightbox } from "./Lightbox";
|
|
|
31
31
|
export type { LogTableEntry } from "./LogEntriesTable";
|
|
32
32
|
export { default as LogEntriesTable } from "./LogEntriesTable";
|
|
33
33
|
export { default as MarkdownView, type MarkdownRenderOptions, type MarkdownViewProps, renderSafeMarkdown } from "./MarkdownView";
|
|
34
|
+
export type { MessageGroupEntry, MessageRowAction, MessageRowAttachment, MessageRowAuthor, MessageRowFile, MessageRowMedia, MessageRowProgress, MessageRowProps, MessageRowQuote, MessageRowReaction, MessageRowStatus, MessageRowThread, MessageSystemRowProps, } from "./MessageRow";
|
|
35
|
+
export { MessageRow, MessageSystemRow, startsMessageGroup } from "./MessageRow";
|
|
34
36
|
export { type MarkdownInfoBlock, type MarkdownInfoBlockRenderInput, type MarkdownInfoBlockType, markdownInfoBlocks, renderMarkdownInfoBlock, scanMarkdownInfoBlock, } from "./markdown-info-blocks";
|
|
35
37
|
export { Pagination, type PaginationProps } from "./Pagination";
|
|
36
38
|
export type { PdfPreviewProps, PdfPreviewRequest } from "./PdfPreview";
|
|
@@ -39,5 +41,7 @@ export type { RangeOption, RangePickerProps } from "./RangePicker";
|
|
|
39
41
|
export { default as RangePicker } from "./RangePicker";
|
|
40
42
|
export type { StructuredDataPreviewMode, StructuredDataPreviewProps, StructuredDataValue } from "./StructuredDataPreview";
|
|
41
43
|
export { default as StructuredDataPreview, isStructuredDataValue } from "./StructuredDataPreview";
|
|
44
|
+
export type { VirtualFeedController, VirtualFeedProps, VirtualFeedScrollOptions } from "./VirtualFeed";
|
|
45
|
+
export { VirtualFeed } from "./VirtualFeed";
|
|
42
46
|
export type { ZoomPanAction, ZoomPanFullscreen, ZoomPanViewportProps } from "./ZoomPanViewport";
|
|
43
47
|
export { ZoomPanViewport } from "./ZoomPanViewport";
|
|
@@ -5,8 +5,9 @@ export type InstallGuideProps = {
|
|
|
5
5
|
appName: string;
|
|
6
6
|
install: InstallPrompt;
|
|
7
7
|
/**
|
|
8
|
-
* The address
|
|
9
|
-
* fails, so it can be copied by hand.
|
|
8
|
+
* The absolute address of the page to install. A browser inside another app copies it, to open it in Safari or
|
|
9
|
+
* Chrome, and shows it as text when copying fails, so it can be copied by hand. Samsung Internet opens an http or
|
|
10
|
+
* https address in Chrome.
|
|
10
11
|
*/
|
|
11
12
|
url: string;
|
|
12
13
|
/**
|
|
@@ -20,7 +21,8 @@ export type InstallGuideProps = {
|
|
|
20
21
|
* Explains how to install the current page as an app on this platform: the browser's own dialog where it offers
|
|
21
22
|
* one, otherwise the steps for Safari on iPhone, iPad, and Mac, other browsers on iPhone and iPad, Android, and other
|
|
22
23
|
* browsers. A browser inside another app cannot install, so it gets a warning and the link to copy into Safari or
|
|
23
|
-
* Chrome instead.
|
|
24
|
+
* Chrome instead. Samsung Internet gets a link to Chrome even when it offers its own dialog, because Android may block
|
|
25
|
+
* the app package it builds. The host owns the surrounding surface, its heading, and dismissal.
|
|
24
26
|
*/
|
|
25
27
|
export declare function InstallGuide(props: InstallGuideProps): JSX.Element;
|
|
26
28
|
export default InstallGuide;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Which installation steps a browser needs. `apple-in-app` and `in-app` are browsers embedded in another app, on
|
|
3
3
|
* iPhone or iPad and elsewhere, which cannot install at all. `apple-browser` is Chrome, Firefox, Edge, or another
|
|
4
|
-
* browser on iPhone or iPad, which installs through its Share menu but less reliably than Safari. `android-
|
|
5
|
-
*
|
|
4
|
+
* browser on iPhone or iPad, which installs through its Share menu but less reliably than Safari. `android-samsung` is
|
|
5
|
+
* Samsung Internet on Android, whose installed apps Android may block as built for an older Android version.
|
|
6
|
+
* `android-browser` is another Android browser, such as Firefox or Edge.
|
|
6
7
|
*/
|
|
7
|
-
export type InstallationPlatform = "in-app" | "apple-in-app" | "apple-browser" | "apple-mobile" | "apple-desktop" | "android-browser" | "android" | "generic";
|
|
8
|
+
export type InstallationPlatform = "in-app" | "apple-in-app" | "apple-browser" | "apple-mobile" | "apple-desktop" | "android-samsung" | "android-browser" | "android" | "generic";
|
|
8
9
|
/**
|
|
9
10
|
* Classifies the browser from its user agent; `platform` and `touchPoints` only tell an iPad that reports a Mac apart.
|
|
10
11
|
* A pure function, so the server and the browser compute the same value from the same user agent. Not a device
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { type JSX } from "solid-js";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Why the scanner could not start, as far as the browser tells: `"denied"` when camera access is off, `"no-camera"`
|
|
4
|
+
* when the device has no camera, `"in-use"` when the camera is busy or could not start, most often because another app
|
|
5
|
+
* holds it, and `"unavailable"` for anything else, including a scanning engine that cannot load.
|
|
6
|
+
*/
|
|
7
|
+
export type QrScannerError = "denied" | "no-camera" | "in-use" | "unavailable";
|
|
3
8
|
export type QrScannerProps = {
|
|
4
9
|
/** Decoded text is untrusted. Return `true` to accept it and stop the camera, `false` to reject it and keep scanning. */
|
|
5
10
|
onResult: (text: string) => boolean;
|
|
6
11
|
/** The page was hidden or left; unmount the scanner. */
|
|
7
12
|
onStop: () => void;
|
|
8
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The camera or the scanning engine could not start; the scanner has stopped. Offer another way in. A frame that
|
|
15
|
+
* cannot be decoded never ends here.
|
|
16
|
+
*/
|
|
9
17
|
onError: (reason: QrScannerError) => void;
|
|
10
18
|
/** What to point the camera at. Defaults to a generic QR code hint. */
|
|
11
19
|
instructions?: string;
|
|
@@ -61,6 +61,8 @@ declare const uiMessages: import("@k2b/stdlib").Catalog<{
|
|
|
61
61
|
hidePassword: string;
|
|
62
62
|
noColumns: string;
|
|
63
63
|
noData: string;
|
|
64
|
+
viewRaw: string;
|
|
65
|
+
viewFormatted: string;
|
|
64
66
|
noRecords: string;
|
|
65
67
|
noTagsYet: string;
|
|
66
68
|
noResultsFound: string;
|
|
@@ -192,6 +194,42 @@ declare const uiMessages: import("@k2b/stdlib").Catalog<{
|
|
|
192
194
|
dropFilesToAttach: string;
|
|
193
195
|
conversation: string;
|
|
194
196
|
jumpToLatest: string;
|
|
197
|
+
feedJumpToLatest: string;
|
|
198
|
+
feedJumpToLatestCount: ({ count }: {
|
|
199
|
+
count: number;
|
|
200
|
+
}) => string;
|
|
201
|
+
feedNewItems: ({ count }: {
|
|
202
|
+
count: number;
|
|
203
|
+
}) => string;
|
|
204
|
+
feedNewMarker: string;
|
|
205
|
+
messageSent: string;
|
|
206
|
+
messageNotSent: string;
|
|
207
|
+
messageRetry: string;
|
|
208
|
+
messageShowMore: string;
|
|
209
|
+
messageShowLess: string;
|
|
210
|
+
messageReplyTo: string;
|
|
211
|
+
messageForwarded: string;
|
|
212
|
+
messageEdited: string;
|
|
213
|
+
messageDeleted: string;
|
|
214
|
+
messageVideo: string;
|
|
215
|
+
messageMoreAttachments: ({ count }: {
|
|
216
|
+
count: number;
|
|
217
|
+
}) => string;
|
|
218
|
+
messageReactions: string;
|
|
219
|
+
messageReaction: ({ emoji, count, names, own }: {
|
|
220
|
+
emoji: string;
|
|
221
|
+
count: number;
|
|
222
|
+
names?: string;
|
|
223
|
+
own?: boolean;
|
|
224
|
+
}) => string;
|
|
225
|
+
messageAddReaction: string;
|
|
226
|
+
messageReplies: ({ count }: {
|
|
227
|
+
count: number;
|
|
228
|
+
}) => string;
|
|
229
|
+
messageLastReply: ({ time }: {
|
|
230
|
+
time: string;
|
|
231
|
+
}) => string;
|
|
232
|
+
messageStop: string;
|
|
195
233
|
conversationMessages: ({ label }: {
|
|
196
234
|
label: string;
|
|
197
235
|
}) => string;
|
|
@@ -467,6 +505,11 @@ declare const uiMessages: import("@k2b/stdlib").Catalog<{
|
|
|
467
505
|
installAppleBrowserDetail: string;
|
|
468
506
|
installAndroidBrowserTitle: string;
|
|
469
507
|
installAndroidBrowserDetail: string;
|
|
508
|
+
installSamsungTitle: string;
|
|
509
|
+
installSamsungDetail: ({ appName }: {
|
|
510
|
+
appName: string;
|
|
511
|
+
}) => string;
|
|
512
|
+
installOpenChrome: string;
|
|
470
513
|
installCopyLink: string;
|
|
471
514
|
installLinkCopied: string;
|
|
472
515
|
installCopyFailed: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k2b/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Production-ready components for SolidJS applications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"import": "./dist/ssr/index.js",
|
|
22
22
|
"default": "./dist/ssr/index.js"
|
|
23
23
|
},
|
|
24
|
+
"./base.css": "./dist/base.css",
|
|
24
25
|
"./global.css": "./dist/global.css",
|
|
25
26
|
"./styles.css": "./dist/styles.css",
|
|
26
27
|
"./fonts/plex.css": "./dist/plex.css",
|
|
@@ -59,6 +60,7 @@
|
|
|
59
60
|
"@k2b/ssr": "0.14.0",
|
|
60
61
|
"@types/babel__core": "7.20.5",
|
|
61
62
|
"@types/bun": "1.4.2",
|
|
63
|
+
"axe-core": "4.11.0",
|
|
62
64
|
"babel-preset-solid": "1.9.15",
|
|
63
65
|
"bun-plugin-tailwind": "0.1.2",
|
|
64
66
|
"happy-dom": "20.14.5",
|