@seekbuddy/dsh-ui 0.0.0-stage → 0.2.0-beta.1
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/CHANGELOG.md +83 -0
- package/LICENSE +22 -0
- package/README.md +175 -2
- package/README.zh.md +176 -0
- package/THIRD_PARTY_NOTICES.md +42 -0
- package/UPSTREAM.md +59 -0
- package/dist/blocks.js +1617 -0
- package/dist/chunks/chunk-23KOEBWJ.js +104 -0
- package/dist/chunks/chunk-6SGSJ5KW.js +57 -0
- package/dist/chunks/chunk-7NH2UOZO.js +155 -0
- package/dist/chunks/chunk-7SKW4S35.js +66 -0
- package/dist/chunks/chunk-B3EEK7A2.js +408 -0
- package/dist/chunks/chunk-CEBTQO6W.js +24 -0
- package/dist/chunks/chunk-ENKPNYOB.js +26 -0
- package/dist/chunks/chunk-EWAZFWLW.js +27 -0
- package/dist/chunks/chunk-F352IICS.js +57 -0
- package/dist/chunks/chunk-FFJ6TCCF.js +31 -0
- package/dist/chunks/chunk-FZXK4LTI.js +129 -0
- package/dist/chunks/chunk-JA3XDLIA.js +1115 -0
- package/dist/chunks/chunk-L7XALG4J.js +36 -0
- package/dist/chunks/chunk-OCAQFVT3.js +3172 -0
- package/dist/chunks/chunk-RAXDA2PT.js +202 -0
- package/dist/chunks/chunk-RNVSCTW7.js +24 -0
- package/dist/chunks/chunk-RZOP2PFC.js +152 -0
- package/dist/chunks/chunk-SN6RSUWC.js +61 -0
- package/dist/chunks/chunk-SNVSQWCU.js +22 -0
- package/dist/chunks/chunk-SO3DCAWG.js +170 -0
- package/dist/chunks/chunk-UAEFKTV3.js +144 -0
- package/dist/chunks/chunk-UGEORMLD.js +89 -0
- package/dist/chunks/chunk-W6FLI3AK.js +112 -0
- package/dist/chunks/chunk-WX46TSKP.js +328 -0
- package/dist/chunks/chunk-XL33IPCV.js +261 -0
- package/dist/chunks/chunk-XW4L4ZGL.js +967 -0
- package/dist/chunks/chunk-YOBY6PSL.js +850 -0
- package/dist/chunks/chunk-ZA47FP7C.js +7 -0
- package/dist/icons.js +859 -0
- package/dist/index.js +1675 -0
- package/dist/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/katex.css +1 -0
- package/dist/katex.css.d.ts +2 -0
- package/dist/markdown.js +225 -0
- package/dist/meta.json +7575 -0
- package/dist/root-inputs.json +86 -0
- package/dist/seekbuddy-card.js +7 -0
- package/dist/seekbuddy-empty.js +8 -0
- package/dist/seekbuddy-internal/DangerButton.js +7 -0
- package/dist/seekbuddy-internal/Mark.js +7 -0
- package/dist/seekbuddy-internal/Message.js +10 -0
- package/dist/seekbuddy-internal/Pagination.js +9 -0
- package/dist/seekbuddy-internal/StatusBadge.js +7 -0
- package/dist/seekbuddy-internal/SubtleButton.js +7 -0
- package/dist/seekbuddy-internal/Switch.js +7 -0
- package/dist/seekbuddy-internal/Upload.js +7 -0
- package/dist/seekbuddy-internal/date/Calendar.js +8 -0
- package/dist/seekbuddy-internal/date/DatePicker.js +9 -0
- package/dist/seekbuddy-internal/date/DateRangePicker.js +9 -0
- package/dist/seekbuddy-internal/date/TimePicker.js +8 -0
- package/dist/seekbuddy-internal/date/fields.js +16 -0
- package/dist/seekbuddy-internal/qr/QrCode.js +7 -0
- package/dist/seekbuddy-spinner.js +7 -0
- package/dist/seekbuddy-tabs.js +7 -0
- package/dist/seekbuddy-timeline.js +8 -0
- package/dist/seekbuddy.js +89 -0
- package/dist/theme-bootstrap.js +13 -0
- package/dist/theme.js +37 -0
- package/dist/tokens.css +974 -0
- package/dist/tokens.css.d.ts +2 -0
- package/dist/types/AnimatedRows.d.ts +45 -0
- package/dist/types/Button.d.ts +18 -0
- package/dist/types/Checkbox.d.ts +19 -0
- package/dist/types/CodeFileIcon.d.ts +11 -0
- package/dist/types/CodeToolbar.d.ts +29 -0
- package/dist/types/CommandText.d.ts +15 -0
- package/dist/types/ConfigField.d.ts +32 -0
- package/dist/types/ConnectionIndicator.d.ts +25 -0
- package/dist/types/DetailDocument.d.ts +77 -0
- package/dist/types/DiffBlock.d.ts +51 -0
- package/dist/types/DisclosureRow.d.ts +37 -0
- package/dist/types/DraggableImage.d.ts +18 -0
- package/dist/types/FileTypeIcon.d.ts +42 -0
- package/dist/types/FoldToggle.d.ts +19 -0
- package/dist/types/HoverCard.d.ts +44 -0
- package/dist/types/HoverCardGroup.d.ts +24 -0
- package/dist/types/ImageLightbox.d.ts +29 -0
- package/dist/types/ImagePreview.d.ts +11 -0
- package/dist/types/InlineEditor.d.ts +22 -0
- package/dist/types/Input.d.ts +11 -0
- package/dist/types/JsonTree.d.ts +58 -0
- package/dist/types/LinkIcon.d.ts +33 -0
- package/dist/types/Menu.d.ts +163 -0
- package/dist/types/MenuGroup.d.ts +21 -0
- package/dist/types/MenuSurface.d.ts +24 -0
- package/dist/types/Modal.d.ts +43 -0
- package/dist/types/PermissionIcon.d.ts +50 -0
- package/dist/types/Pill.d.ts +12 -0
- package/dist/types/QuotePreview.d.ts +23 -0
- package/dist/types/ReadBlock.d.ts +47 -0
- package/dist/types/ReferenceIcon.d.ts +20 -0
- package/dist/types/RiskConfirmation.d.ts +19 -0
- package/dist/types/SearchBlock.d.ts +71 -0
- package/dist/types/SegmentedControl.d.ts +34 -0
- package/dist/types/SegmentedTabs.d.ts +27 -0
- package/dist/types/ShortcutKeys.d.ts +10 -0
- package/dist/types/SiteGlyph.d.ts +24 -0
- package/dist/types/StateDot.d.ts +19 -0
- package/dist/types/Switch.d.ts +19 -0
- package/dist/types/Tag.d.ts +31 -0
- package/dist/types/TerminalBlock.d.ts +85 -0
- package/dist/types/TextShimmer.d.ts +22 -0
- package/dist/types/Toast.d.ts +48 -0
- package/dist/types/Tooltip.d.ts +69 -0
- package/dist/types/UserMessageBubble.d.ts +10 -0
- package/dist/types/WebBlock.d.ts +60 -0
- package/dist/types/ZoomControls.d.ts +26 -0
- package/dist/types/ansi.d.ts +16 -0
- package/dist/types/blocks.d.ts +21 -0
- package/dist/types/clipboard.d.ts +8 -0
- package/dist/types/code-file-icon-artwork.d.ts +53 -0
- package/dist/types/code-file-types.d.ts +29 -0
- package/dist/types/code-highlighting.d.ts +11 -0
- package/dist/types/css-modules.d.ts +6 -0
- package/dist/types/darwin-desktop.d.ts +8 -0
- package/dist/types/document-zoom.d.ts +16 -0
- package/dist/types/file-drag-actions.d.ts +36 -0
- package/dist/types/file-size.d.ts +7 -0
- package/dist/types/focus.d.ts +15 -0
- package/dist/types/guide-artwork.d.ts +14 -0
- package/dist/types/head-tail-cap.d.ts +22 -0
- package/dist/types/icons/artwork.d.ts +421 -0
- package/dist/types/icons/index.d.ts +397 -0
- package/dist/types/icons/props.d.ts +8 -0
- package/dist/types/icons/shared-artwork.d.ts +36 -0
- package/dist/types/icons.d.ts +6 -0
- package/dist/types/image-drag.d.ts +16 -0
- package/dist/types/index.d.ts +71 -0
- package/dist/types/input-modality.d.ts +18 -0
- package/dist/types/keyboard-composition.d.ts +10 -0
- package/dist/types/markdown/CodeBlock.d.ts +34 -0
- package/dist/types/markdown/JsonBlock.d.ts +7 -0
- package/dist/types/markdown/MarkdownDelegate.d.ts +68 -0
- package/dist/types/markdown/MarkdownText.d.ts +54 -0
- package/dist/types/markdown/cjkFriendlyStrong.d.ts +8 -0
- package/dist/types/markdown/file-link.d.ts +22 -0
- package/dist/types/markdown/highlight.d.ts +169 -0
- package/dist/types/markdown/incremental.d.ts +79 -0
- package/dist/types/markdown/katex.d.ts +18 -0
- package/dist/types/markdown/local-image-syntax.d.ts +9 -0
- package/dist/types/markdown/mathCompatibility.d.ts +10 -0
- package/dist/types/markdown/parse.d.ts +24 -0
- package/dist/types/markdown/plain-text.d.ts +21 -0
- package/dist/types/markdown/quote-text.d.ts +7 -0
- package/dist/types/markdown/render.d.ts +145 -0
- package/dist/types/markdown/useViewportHighlighting.d.ts +10 -0
- package/dist/types/markdown/windows-path-destinations.d.ts +10 -0
- package/dist/types/markdown.d.ts +12 -0
- package/dist/types/overlay-top-margin.d.ts +14 -0
- package/dist/types/plugin-artwork.d.ts +16 -0
- package/dist/types/pointer-grace.d.ts +21 -0
- package/dist/types/rank-by-name.d.ts +21 -0
- package/dist/types/relative-time.d.ts +22 -0
- package/dist/types/seekbuddy/Card.d.ts +28 -0
- package/dist/types/seekbuddy/DangerButton.d.ts +31 -0
- package/dist/types/seekbuddy/Empty.d.ts +34 -0
- package/dist/types/seekbuddy/Mark.d.ts +27 -0
- package/dist/types/seekbuddy/Message.d.ts +52 -0
- package/dist/types/seekbuddy/Pagination.d.ts +66 -0
- package/dist/types/seekbuddy/Spinner.d.ts +20 -0
- package/dist/types/seekbuddy/StatusBadge.d.ts +33 -0
- package/dist/types/seekbuddy/SubtleButton.d.ts +30 -0
- package/dist/types/seekbuddy/Switch.d.ts +36 -0
- package/dist/types/seekbuddy/Tabs.d.ts +49 -0
- package/dist/types/seekbuddy/Timeline.d.ts +42 -0
- package/dist/types/seekbuddy/Upload.d.ts +101 -0
- package/dist/types/seekbuddy/date/Calendar.d.ts +94 -0
- package/dist/types/seekbuddy/date/DatePicker.d.ts +29 -0
- package/dist/types/seekbuddy/date/DateRangePicker.d.ts +41 -0
- package/dist/types/seekbuddy/date/TimePicker.d.ts +35 -0
- package/dist/types/seekbuddy/date/date.d.ts +79 -0
- package/dist/types/seekbuddy/date/fields.d.ts +45 -0
- package/dist/types/seekbuddy/index.d.ts +49 -0
- package/dist/types/seekbuddy/qr/QrCode.d.ts +37 -0
- package/dist/types/seekbuddy/qr/qr.d.ts +38 -0
- package/dist/types/theme-bootstrap.d.ts +3 -0
- package/dist/types/theme-core.d.ts +14 -0
- package/dist/types/theme.d.ts +4 -0
- package/dist/types/tooltip-placement.d.ts +34 -0
- package/dist/types/use-clipboard-copy.d.ts +13 -0
- package/dist/types/useAnchoredMaxHeight.d.ts +13 -0
- package/dist/types/useAnchoredPosition.d.ts +35 -0
- package/dist/types/useDismissOnOutsidePointer.d.ts +10 -0
- package/dist/types/useModalLayer.d.ts +26 -0
- package/dist/types/useRowDragPreview.d.ts +19 -0
- package/dist/types/user-text.d.ts +31 -0
- package/package.json +151 -4
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** `button`: a trigger button above the list. `dragger`: a dashed drop zone above the list. */
|
|
2
|
+
export type UploadLayout = 'button' | 'dragger';
|
|
3
|
+
export type UploadStatus = 'uploading' | 'done' | 'error';
|
|
4
|
+
export interface UploadItem {
|
|
5
|
+
/** Stable identity of the item. */
|
|
6
|
+
uid: string;
|
|
7
|
+
/** File name shown in the list. */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Bytes. */
|
|
10
|
+
size: number;
|
|
11
|
+
/** Transfer state of the item. */
|
|
12
|
+
status: UploadStatus;
|
|
13
|
+
/** 0–100. */
|
|
14
|
+
percent: number;
|
|
15
|
+
/** Present for files picked locally; absent on items the caller backfills from history. */
|
|
16
|
+
file?: File | undefined;
|
|
17
|
+
/** Resolved value of `upload()`. */
|
|
18
|
+
response?: unknown;
|
|
19
|
+
/** `Error.message` when `upload()` rejected. */
|
|
20
|
+
error?: string | undefined;
|
|
21
|
+
/** Address of a backfilled item, for `onPreview`. */
|
|
22
|
+
url?: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Why a picked file was refused before entering the list. */
|
|
25
|
+
export type UploadRejectReason = 'accept' | 'size' | 'count';
|
|
26
|
+
export interface UploadRejection {
|
|
27
|
+
/** The refused file. */
|
|
28
|
+
file: File;
|
|
29
|
+
/** Which check refused it. */
|
|
30
|
+
reason: UploadRejectReason;
|
|
31
|
+
}
|
|
32
|
+
/** All user-visible text, localized by the caller. */
|
|
33
|
+
export interface UploadLabels {
|
|
34
|
+
/** Button caption; the drop zone's title in the `dragger` layout. */
|
|
35
|
+
trigger: string;
|
|
36
|
+
/** Caption under the trigger, e.g. ".zip only, up to 10 MB". */
|
|
37
|
+
hint?: string | undefined;
|
|
38
|
+
/** `aria-label` of the file list. */
|
|
39
|
+
list: string;
|
|
40
|
+
/** `aria-label` of an item's remove button. */
|
|
41
|
+
remove: string;
|
|
42
|
+
/** `aria-label` of a failed item's retry button. */
|
|
43
|
+
retry: string;
|
|
44
|
+
/** Status text of an item in progress; also names its progress bar. */
|
|
45
|
+
uploading: string;
|
|
46
|
+
/** Status text of a finished item. */
|
|
47
|
+
done: string;
|
|
48
|
+
/** Status text of a failed item. */
|
|
49
|
+
error: string;
|
|
50
|
+
}
|
|
51
|
+
export interface UploadProps {
|
|
52
|
+
/** Default `button`. */
|
|
53
|
+
layout?: UploadLayout | undefined;
|
|
54
|
+
/** Same grammar as the input `accept` attribute; non-matching files go to `onReject('accept')`. */
|
|
55
|
+
accept?: string | undefined;
|
|
56
|
+
/** Default `false`: a drop of several files keeps the first. */
|
|
57
|
+
multiple?: boolean | undefined;
|
|
58
|
+
/** Upper bound on list length; `1` makes a new file replace the current one (antd). */
|
|
59
|
+
maxCount?: number | undefined;
|
|
60
|
+
/** Bytes; larger files go to `onReject('size')`. */
|
|
61
|
+
maxSize?: number | undefined;
|
|
62
|
+
/** Disables picking, dropping, retry and remove. */
|
|
63
|
+
disabled?: boolean | undefined;
|
|
64
|
+
/** Controlled list; echo `onChange` back. Omit for uncontrolled with `defaultItems`. */
|
|
65
|
+
items?: UploadItem[] | undefined;
|
|
66
|
+
/** Initial list when uncontrolled. */
|
|
67
|
+
defaultItems?: UploadItem[] | undefined;
|
|
68
|
+
/** Extra check after the built-in ones (e.g. a ZIP magic number); `false` or a rejection keeps the file out. */
|
|
69
|
+
beforeUpload?: ((file: File, files: File[]) => boolean | Promise<boolean>) | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* The only transport hook (antd `customRequest`). Resolve → `done` with the value as `response`;
|
|
72
|
+
* reject → `error` with the message. `signal` aborts when the item is removed mid-flight.
|
|
73
|
+
*/
|
|
74
|
+
upload: (file: File, context: {
|
|
75
|
+
onProgress: (percent: number) => void;
|
|
76
|
+
signal: AbortSignal;
|
|
77
|
+
}) => Promise<unknown>;
|
|
78
|
+
/** Every list change: additions, progress, completion, removal. */
|
|
79
|
+
onChange?: ((items: UploadItem[]) => void) | undefined;
|
|
80
|
+
/** Files refused by `accept` / `maxSize` / `maxCount`, batched per pick, for the caller to toast. */
|
|
81
|
+
onReject?: ((rejections: UploadRejection[]) => void) | undefined;
|
|
82
|
+
/** Return `false` to keep the item. */
|
|
83
|
+
onRemove?: ((item: UploadItem) => boolean | Promise<boolean>) | undefined;
|
|
84
|
+
/** Makes file names clickable. */
|
|
85
|
+
onPreview?: ((item: UploadItem) => void) | undefined;
|
|
86
|
+
/** Default `true`. */
|
|
87
|
+
showList?: boolean | undefined;
|
|
88
|
+
/** All visible and screen-reader text; see `UploadLabels`. */
|
|
89
|
+
labels: UploadLabels;
|
|
90
|
+
/** Extra class on the root element, for layout. */
|
|
91
|
+
className?: string | undefined;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* File picker with a status list: pick or drop → built-in `accept` / `maxSize` / `maxCount`
|
|
95
|
+
* filter → `beforeUpload` → the item enters the list as `uploading` and `upload()` runs with a
|
|
96
|
+
* progress callback and an abort signal. The component never talks to the network itself — the
|
|
97
|
+
* transport (multipart POST, presigned PUT, …) belongs to the caller. Text comes
|
|
98
|
+
* from `labels`; the component has no strings of its own. Client Component (state, refs),
|
|
99
|
+
* aggregate entry only.
|
|
100
|
+
*/
|
|
101
|
+
export declare function Upload({ layout, accept, multiple, maxCount, maxSize, disabled, items, defaultItems, beforeUpload, upload, onChange, onReject, onRemove, onPreview, showList, labels, className, }: UploadProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { DateRange, IsoDate, IsoMonth, WeekStart } from './date.js';
|
|
2
|
+
/** Cell state handed to `labels.dayLabel` so the caller can phrase the screen-reader sentence. */
|
|
3
|
+
export interface CalendarDayState {
|
|
4
|
+
/** Single mode: the value. Range mode: the start or the end. */
|
|
5
|
+
selected: boolean;
|
|
6
|
+
/** The cell is today (`today` prop, or the host's local date). */
|
|
7
|
+
today: boolean;
|
|
8
|
+
/** Outside `min` / `max` or refused by `isDateDisabled`. */
|
|
9
|
+
disabled: boolean;
|
|
10
|
+
/** Range mode: inside the committed range (ends included). Always false in single mode. */
|
|
11
|
+
inRange: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface CalendarLabels {
|
|
14
|
+
/** `aria-label` of the previous-month button. */
|
|
15
|
+
previousMonth: string;
|
|
16
|
+
/** `aria-label` of the next-month button. */
|
|
17
|
+
nextMonth: string;
|
|
18
|
+
/** `aria-label` of the previous-year button. */
|
|
19
|
+
previousYear: string;
|
|
20
|
+
/** `aria-label` of the next-year button. */
|
|
21
|
+
nextYear: string;
|
|
22
|
+
/**
|
|
23
|
+
* Screen-reader name of one day cell, `(date, state)` → a full sentence such as
|
|
24
|
+
* "Wednesday, November 24, 2032, selected". Week / month names come from `locale`; this is the only per-cell copy.
|
|
25
|
+
*/
|
|
26
|
+
dayLabel: (date: IsoDate, state: CalendarDayState) => string;
|
|
27
|
+
}
|
|
28
|
+
export interface CalendarBaseProps {
|
|
29
|
+
/** Controlled visible month (the left one when two are shown); uncontrolled follows `value`, then `today`. */
|
|
30
|
+
month?: IsoMonth | undefined;
|
|
31
|
+
/** Called with the new visible month when the user navigates. */
|
|
32
|
+
onMonthChange?: ((month: IsoMonth) => void) | undefined;
|
|
33
|
+
/** Months side by side; single mode defaults to 1, range mode to 2. */
|
|
34
|
+
numberOfMonths?: 1 | 2 | undefined;
|
|
35
|
+
/** Earliest selectable day, inclusive. */
|
|
36
|
+
min?: IsoDate | undefined;
|
|
37
|
+
/** Latest selectable day, inclusive. */
|
|
38
|
+
max?: IsoDate | undefined;
|
|
39
|
+
/** Extra disabling rule on top of `min` / `max` ("weekdays only"). */
|
|
40
|
+
isDateDisabled?: ((date: IsoDate) => boolean) | undefined;
|
|
41
|
+
/** BCP 47 tag driving weekday / month names; defaults to the browser language. */
|
|
42
|
+
locale?: string | undefined;
|
|
43
|
+
/** 1 = Monday (default), 0 = Sunday. */
|
|
44
|
+
weekStart?: WeekStart | undefined;
|
|
45
|
+
/** Injected "today" for tests and non-local zones; defaults to the host's local date. */
|
|
46
|
+
today?: IsoDate | undefined;
|
|
47
|
+
/** Navigation and screen-reader text; see `CalendarLabels`. */
|
|
48
|
+
labels: CalendarLabels;
|
|
49
|
+
/** Move focus to the tab-stop cell (selected → today → first enabled) on mount. */
|
|
50
|
+
autoFocus?: boolean | undefined;
|
|
51
|
+
/** Extra class on the root element, for layout. */
|
|
52
|
+
className?: string | undefined;
|
|
53
|
+
}
|
|
54
|
+
export interface CalendarSingleProps extends CalendarBaseProps {
|
|
55
|
+
/** `single` picks one day; `range` picks a start and an end. */
|
|
56
|
+
mode: 'single';
|
|
57
|
+
/** Selected day, or `null` for none. */
|
|
58
|
+
value: IsoDate | null;
|
|
59
|
+
/** Called with the picked day. */
|
|
60
|
+
onChange: (date: IsoDate) => void;
|
|
61
|
+
}
|
|
62
|
+
/** A range whose end is still being picked (`end: null`); `DateRange` is the completed form. */
|
|
63
|
+
export interface DateRangeDraft {
|
|
64
|
+
/** The first picked day. */
|
|
65
|
+
start: IsoDate;
|
|
66
|
+
/** `null` until the second day is picked. */
|
|
67
|
+
end: IsoDate | null;
|
|
68
|
+
}
|
|
69
|
+
export interface CalendarRangeProps extends CalendarBaseProps {
|
|
70
|
+
/** `single` picks one day; `range` picks a start and an end. */
|
|
71
|
+
mode: 'range';
|
|
72
|
+
/** Pass the draft back as-is while the end is pending — the component is fully controlled. */
|
|
73
|
+
value: DateRange | DateRangeDraft | null;
|
|
74
|
+
/**
|
|
75
|
+
* First pick → `{ start, end: null }`; second pick → the ordered `DateRange` (a reversed
|
|
76
|
+
* pick swaps the ends). A third pick starts a new draft.
|
|
77
|
+
*/
|
|
78
|
+
onChange: (range: DateRange | DateRangeDraft) => void;
|
|
79
|
+
}
|
|
80
|
+
export type CalendarProps = CalendarSingleProps | CalendarRangeProps;
|
|
81
|
+
/** Position of a cell inside a committed or previewed range (`data-range` / `data-range-preview`). */
|
|
82
|
+
export type CalendarRangePosition = 'start' | 'middle' | 'end' | 'single';
|
|
83
|
+
/**
|
|
84
|
+
* Month grid with WAI-ARIA grid keyboard support: one roving tab stop for the whole calendar,
|
|
85
|
+
* arrows move by day / week, Home / End to the week's ends, PageUp / PageDown by month
|
|
86
|
+
* (Shift: by year), Enter / Space pick. Moving focus past the visible months turns the page.
|
|
87
|
+
* Padding days from the neighbouring months are visible, clickable (they turn the page as
|
|
88
|
+
* they pick) and never the tab stop. Range mode adds a two-pick state machine: after the
|
|
89
|
+
* start is picked, hovering or keyboard-focusing a day previews the range (`data-range-preview`),
|
|
90
|
+
* the second pick commits it ordered, and committed cells carry `data-range` positions.
|
|
91
|
+
* Upstream primitives ship no calendar, so this package provides
|
|
92
|
+
* one; `DatePicker` / `DateRangePicker` compose it.
|
|
93
|
+
*/
|
|
94
|
+
export declare function Calendar(props: CalendarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CalendarBaseProps, CalendarLabels } from './Calendar.js';
|
|
2
|
+
import type { IsoDate } from './date.js';
|
|
3
|
+
export interface DatePickerLabels extends CalendarLabels {
|
|
4
|
+
/** The "Today" shortcut button. */
|
|
5
|
+
today: string;
|
|
6
|
+
/** Footer text while nothing is selected. */
|
|
7
|
+
empty: string;
|
|
8
|
+
}
|
|
9
|
+
export interface DatePickerProps extends Omit<CalendarBaseProps, 'numberOfMonths' | 'labels'> {
|
|
10
|
+
/** Selected day, or `null` for none. */
|
|
11
|
+
value: IsoDate | null;
|
|
12
|
+
/** Fires on every cell pick and on "Today" — no draft / apply step. */
|
|
13
|
+
onChange: (date: IsoDate) => void;
|
|
14
|
+
/** All visible and screen-reader text; see `DatePickerLabels`. */
|
|
15
|
+
labels: DatePickerLabels;
|
|
16
|
+
/**
|
|
17
|
+
* Footer rendering of the selected day; defaults to an Intl medium date with a short weekday
|
|
18
|
+
* in `locale` ("Wed, Nov 24, 2032" / "2032年11月24日周三").
|
|
19
|
+
*/
|
|
20
|
+
formatSelected?: ((date: IsoDate) => string) | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Single-date panel: `Calendar mode="single"` plus a footer
|
|
24
|
+
* with the formatted selection on the left and a "Today" shortcut on the right. "Today" turns
|
|
25
|
+
* the page to the current month and selects it; it is disabled when today is outside
|
|
26
|
+
* `min` / `max` or rejected by `isDateDisabled`. The month is owned here (controlled into the
|
|
27
|
+
* calendar) so the shortcut can turn the page even when today is already the value.
|
|
28
|
+
*/
|
|
29
|
+
export declare function DatePicker({ value, onChange, labels, formatSelected, month, onMonthChange, min, max, isDateDisabled, locale, today: todayProp, className, ...calendar }: DatePickerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CalendarBaseProps, CalendarLabels } from './Calendar.js';
|
|
2
|
+
import type { DateRange } from './date.js';
|
|
3
|
+
export interface DateRangePreset {
|
|
4
|
+
/** Stable identity of the preset. */
|
|
5
|
+
key: string;
|
|
6
|
+
/** Visible preset text, e.g. "Last 7 days". */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Computed by the caller — "last 7 days" depends on today and the time zone, not on the component. */
|
|
9
|
+
range: DateRange;
|
|
10
|
+
}
|
|
11
|
+
export interface DateRangePickerLabels extends CalendarLabels {
|
|
12
|
+
/** Accessible name of the presets list. */
|
|
13
|
+
presets: string;
|
|
14
|
+
/** Caption of the button that discards the draft. */
|
|
15
|
+
cancel: string;
|
|
16
|
+
/** Caption of the button that commits the range. */
|
|
17
|
+
apply: string;
|
|
18
|
+
/** Status shown (and announced) while the start is picked and the end is still pending. */
|
|
19
|
+
pickEnd: string;
|
|
20
|
+
}
|
|
21
|
+
export interface DateRangePickerProps extends Omit<CalendarBaseProps, 'labels'> {
|
|
22
|
+
/** Committed range, or `null` for none. */
|
|
23
|
+
value: DateRange | null;
|
|
24
|
+
/** Fires only when "Apply" is pressed with a complete range. */
|
|
25
|
+
onChange: (range: DateRange) => void;
|
|
26
|
+
/** Fires after "Cancel" rolled the draft back to `value`. */
|
|
27
|
+
onCancel?: (() => void) | undefined;
|
|
28
|
+
/** Shortcut ranges listed on the left; omit to hide the list. */
|
|
29
|
+
presets?: ReadonlyArray<DateRangePreset> | undefined;
|
|
30
|
+
/** All visible and screen-reader text; see `DateRangePickerLabels`. */
|
|
31
|
+
labels: DateRangePickerLabels;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Range panel: presets on the left, a two-month range
|
|
35
|
+
* `Calendar` in the middle, "Cancel / Apply" below. Picks inside the panel only edit a draft;
|
|
36
|
+
* `onChange` fires once on "Apply" with a complete range, "Cancel" restores `value` and calls
|
|
37
|
+
* `onCancel`. Choosing a preset replaces the draft and turns the page to its start month; a
|
|
38
|
+
* preset shows a check while the draft equals it exactly. The month is owned here (controlled
|
|
39
|
+
* into the calendar) so presets can turn the page. Tab order: presets → calendar → Cancel → Apply.
|
|
40
|
+
*/
|
|
41
|
+
export declare function DateRangePicker({ value, onChange, onCancel, presets, labels, month, onMonthChange, numberOfMonths, today: todayProp, className, ...calendar }: DateRangePickerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { IsoTime } from './date.js';
|
|
2
|
+
export type MinuteStep = 1 | 5 | 10 | 15 | 30;
|
|
3
|
+
export interface TimePickerLabels {
|
|
4
|
+
/** Hours column heading, also the listbox's accessible name. */
|
|
5
|
+
hours: string;
|
|
6
|
+
/** Minutes column heading, also the listbox's accessible name. */
|
|
7
|
+
minutes: string;
|
|
8
|
+
}
|
|
9
|
+
export interface TimePickerProps {
|
|
10
|
+
/** 24-hour `HH:mm`; `null` highlights the 00:00 position without reporting a value. */
|
|
11
|
+
value: IsoTime | null;
|
|
12
|
+
/** Fires on every pick — column click or ↑ / ↓ / Home / End inside a column. */
|
|
13
|
+
onChange: (time: IsoTime) => void;
|
|
14
|
+
/** Minute granularity; the minutes column lists only multiples of the step. Default 1. */
|
|
15
|
+
minuteStep?: MinuteStep | undefined;
|
|
16
|
+
/** Earliest selectable time, inclusive; earlier options are disabled. */
|
|
17
|
+
min?: IsoTime | undefined;
|
|
18
|
+
/** Latest selectable time, inclusive; later options are disabled. */
|
|
19
|
+
max?: IsoTime | undefined;
|
|
20
|
+
/** Column headings; see `TimePickerLabels`. */
|
|
21
|
+
labels: TimePickerLabels;
|
|
22
|
+
/** Focus the hours column on mount. */
|
|
23
|
+
autoFocus?: boolean | undefined;
|
|
24
|
+
/** Extra class on the root element, for layout. */
|
|
25
|
+
className?: string | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Two-column time list: hours 00–23 and minutes in
|
|
29
|
+
* `minuteStep`, each a `role="listbox"` with one tab stop and `aria-activedescendant`;
|
|
30
|
+
* ↑ / ↓ / Home / End move the selection and fire `onChange` at once, clicks do the same,
|
|
31
|
+
* nothing wraps. `min` / `max` disable hours with no reachable minute and minutes outside the
|
|
32
|
+
* window; a pick that would leave the window is clamped into it. The highlighted option
|
|
33
|
+
* scrolls to the column's centre on mount and on every change. Upstream ships no time picker.
|
|
34
|
+
*/
|
|
35
|
+
export declare function TimePicker({ value, onChange, minuteStep, min, max, labels, autoFocus, className, }: TimePickerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Calendar day, `YYYY-MM-DD`. */
|
|
2
|
+
export type IsoDate = `${number}-${number}-${number}`;
|
|
3
|
+
/** Calendar month, `YYYY-MM`. */
|
|
4
|
+
export type IsoMonth = `${number}-${number}`;
|
|
5
|
+
/** Wall-clock time, 24-hour `HH:mm`. */
|
|
6
|
+
export type IsoTime = `${number}:${number}`;
|
|
7
|
+
/** Closed interval, `start <= end`. */
|
|
8
|
+
export interface DateRange {
|
|
9
|
+
/** First day of the range, inclusive. */
|
|
10
|
+
start: IsoDate;
|
|
11
|
+
/** Last day of the range, inclusive. */
|
|
12
|
+
end: IsoDate;
|
|
13
|
+
}
|
|
14
|
+
/** First day of the week: 1 = Monday, 0 = Sunday. */
|
|
15
|
+
export type WeekStart = 0 | 1;
|
|
16
|
+
export interface DateParts {
|
|
17
|
+
y: number;
|
|
18
|
+
m: number;
|
|
19
|
+
d: number;
|
|
20
|
+
}
|
|
21
|
+
/** Days in a month (`m` is 1-based). */
|
|
22
|
+
export declare function daysInMonth(y: number, m: number): number;
|
|
23
|
+
/** Split `YYYY-MM-DD`; throws `RangeError` on malformed or impossible dates ("2025-02-30"). */
|
|
24
|
+
export declare function parseIsoDate(iso: string): DateParts;
|
|
25
|
+
export declare function formatIsoDate({ y, m, d }: DateParts): IsoDate;
|
|
26
|
+
/** Split `YYYY-MM`; throws `RangeError` when malformed. */
|
|
27
|
+
export declare function parseIsoMonth(month: string): {
|
|
28
|
+
y: number;
|
|
29
|
+
m: number;
|
|
30
|
+
};
|
|
31
|
+
export declare function formatIsoMonth(y: number, m: number): IsoMonth;
|
|
32
|
+
/** The month a date belongs to. */
|
|
33
|
+
export declare function monthOf(iso: IsoDate): IsoMonth;
|
|
34
|
+
/** Today in the host's local time zone (the only place local time is consulted). */
|
|
35
|
+
export declare function todayIso(): IsoDate;
|
|
36
|
+
export declare function addDays(iso: IsoDate, n: number): IsoDate;
|
|
37
|
+
export declare function addMonths(month: IsoMonth, n: number): IsoMonth;
|
|
38
|
+
/**
|
|
39
|
+
* Same-day-of-month shift that clamps to the target month's length
|
|
40
|
+
* (2025-01-31 + 1 month → 2025-02-28); used by PageUp / PageDown.
|
|
41
|
+
*/
|
|
42
|
+
export declare function addMonthsToDate(iso: IsoDate, n: number): IsoDate;
|
|
43
|
+
/** Lexicographic order is chronological for zero-padded ISO dates, months and times. */
|
|
44
|
+
export declare function compareIso(a: string, b: string): -1 | 0 | 1;
|
|
45
|
+
/** 0 = Sunday … 6 = Saturday. */
|
|
46
|
+
export declare function weekdayOf(iso: IsoDate): number;
|
|
47
|
+
/** Distance in days from the start of the week (`0` on the week's first day). */
|
|
48
|
+
export declare function weekOffset(iso: IsoDate, weekStart: WeekStart): number;
|
|
49
|
+
/**
|
|
50
|
+
* Six rows × seven columns covering `month`, padded with the surrounding months' days so
|
|
51
|
+
* every rendered grid has the same height (the 42 cells the mockups show in grey).
|
|
52
|
+
*/
|
|
53
|
+
export declare function monthGrid(month: IsoMonth, weekStart: WeekStart): IsoDate[];
|
|
54
|
+
export declare function isInRange(iso: IsoDate, range: DateRange): boolean;
|
|
55
|
+
/** Orders two picks into a closed range (clicking the end before the start swaps them). */
|
|
56
|
+
export declare function normalizeRange(a: IsoDate, b: IsoDate): DateRange;
|
|
57
|
+
/** True when `iso` is outside `[min, max]` (either bound optional). */
|
|
58
|
+
export declare function isOutsideBounds(iso: IsoDate, min: IsoDate | undefined, max: IsoDate | undefined): boolean;
|
|
59
|
+
export type WeekdayNameStyle = 'narrow' | 'short' | 'long';
|
|
60
|
+
/** Seven weekday names in `locale`, starting at `weekStart` ("Mon Tue …" or "一 二 …"). */
|
|
61
|
+
export declare function weekdayNames(locale: string | undefined, weekStart: WeekStart, style?: WeekdayNameStyle): string[];
|
|
62
|
+
/** Month heading in `locale` ("November 2032" / "2032年11月"). */
|
|
63
|
+
export declare function monthTitle(locale: string | undefined, month: IsoMonth): string;
|
|
64
|
+
/** Format a calendar day with any `Intl.DateTimeFormat` options (time zone is pinned to UTC). */
|
|
65
|
+
export declare function formatDate(locale: string | undefined, iso: IsoDate, options: Intl.DateTimeFormatOptions): string;
|
|
66
|
+
/** Full date in `locale` for screen readers ("Wednesday, November 24, 2032"). */
|
|
67
|
+
export declare function formatDateLong(locale: string | undefined, iso: IsoDate): string;
|
|
68
|
+
/** Compact date with weekday for pickers' footers ("Wed, Nov 24, 2032" / "2032年11月24日周三"). */
|
|
69
|
+
export declare function formatDateMedium(locale: string | undefined, iso: IsoDate): string;
|
|
70
|
+
/** Split `HH:mm`; throws `RangeError` outside 00:00–23:59. */
|
|
71
|
+
export declare function parseIsoTime(time: string): {
|
|
72
|
+
h: number;
|
|
73
|
+
min: number;
|
|
74
|
+
};
|
|
75
|
+
export declare function timeToMinutes(time: IsoTime): number;
|
|
76
|
+
/** Minutes since midnight → `HH:mm`; wraps around the day. */
|
|
77
|
+
export declare function minutesToTime(minutes: number): IsoTime;
|
|
78
|
+
/** Clamp into `[min, max]` (either bound optional). */
|
|
79
|
+
export declare function clampTime(time: IsoTime, min: IsoTime | undefined, max: IsoTime | undefined): IsoTime;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { DatePickerProps } from './DatePicker.js';
|
|
2
|
+
import type { DateRangePickerProps } from './DateRangePicker.js';
|
|
3
|
+
import type { TimePickerProps } from './TimePicker.js';
|
|
4
|
+
import type { DateRange, IsoDate, IsoTime } from './date.js';
|
|
5
|
+
/** Labels every trigger adds on top of its panel's labels. */
|
|
6
|
+
export interface FieldLabels {
|
|
7
|
+
/** Read after the value on the trigger ("open date picker") and used as the dialog's name. */
|
|
8
|
+
open: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DateFieldProps extends DatePickerProps {
|
|
11
|
+
/** Trigger text for the value; defaults to `YYYY/MM/DD`. */
|
|
12
|
+
formatValue?: ((date: IsoDate | null) => string) | undefined;
|
|
13
|
+
/** Trigger text while `value` is `null`. */
|
|
14
|
+
placeholder?: string | undefined;
|
|
15
|
+
/** Disables the trigger; the panel cannot open. */
|
|
16
|
+
disabled?: boolean | undefined;
|
|
17
|
+
/** The panel's labels plus `open` for the trigger; see `FieldLabels`. */
|
|
18
|
+
labels: DatePickerProps['labels'] & FieldLabels;
|
|
19
|
+
}
|
|
20
|
+
/** Input-looking trigger that opens a `DatePicker`; a pick (or "Today") closes the panel. */
|
|
21
|
+
export declare function DateField({ formatValue, placeholder, disabled, className, labels, onChange, ...picker }: DateFieldProps): import("react").JSX.Element;
|
|
22
|
+
export interface DateRangeFieldProps extends Omit<DateRangePickerProps, 'onCancel'> {
|
|
23
|
+
/** Trigger text for the value; defaults to `YYYY/MM/DD - YYYY/MM/DD`. */
|
|
24
|
+
formatValue?: ((range: DateRange | null) => string) | undefined;
|
|
25
|
+
/** Trigger text while `value` is `null`. */
|
|
26
|
+
placeholder?: string | undefined;
|
|
27
|
+
/** Disables the trigger; the panel cannot open. */
|
|
28
|
+
disabled?: boolean | undefined;
|
|
29
|
+
/** The panel's labels plus `open` for the trigger; see `FieldLabels`. */
|
|
30
|
+
labels: DateRangePickerProps['labels'] & FieldLabels;
|
|
31
|
+
}
|
|
32
|
+
/** Input-looking trigger that opens a `DateRangePicker`; "Apply" reports and closes, "Cancel" just closes. */
|
|
33
|
+
export declare function DateRangeField({ formatValue, placeholder, disabled, className, labels, onChange, ...picker }: DateRangeFieldProps): import("react").JSX.Element;
|
|
34
|
+
export interface TimeFieldProps extends TimePickerProps {
|
|
35
|
+
/** Trigger text for the value; defaults to the `HH:mm` string itself. */
|
|
36
|
+
formatValue?: ((time: IsoTime | null) => string) | undefined;
|
|
37
|
+
/** Trigger text while `value` is `null`. */
|
|
38
|
+
placeholder?: string | undefined;
|
|
39
|
+
/** Disables the trigger; the panel cannot open. */
|
|
40
|
+
disabled?: boolean | undefined;
|
|
41
|
+
/** The panel's labels plus `open` for the trigger; see `FieldLabels`. */
|
|
42
|
+
labels: TimePickerProps['labels'] & FieldLabels;
|
|
43
|
+
}
|
|
44
|
+
/** Input-looking trigger that opens a `TimePicker`; picks keep the panel open (both columns are usually adjusted). */
|
|
45
|
+
export declare function TimeField({ formatValue, placeholder, disabled, className, labels, ...picker }: TimeFieldProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extra components (`@seekbuddy/dsh-ui/seekbuddy`).
|
|
3
|
+
*
|
|
4
|
+
* Everything outside this directory is a copy of the upstream DSH primitives and
|
|
5
|
+
* is only touched by synchronization (see UPSTREAM.md). Components here are owned
|
|
6
|
+
* by this package and styled only through `--dsw-*` tokens. They must import DSH
|
|
7
|
+
* primitives through the public `@seekbuddy/dsh-ui` entry — never by relative
|
|
8
|
+
* path — so a bundler can alias that entry to another copy of the primitives
|
|
9
|
+
* (such as the one a DSH web shell already loads).
|
|
10
|
+
*/
|
|
11
|
+
export { Calendar } from './date/Calendar.js';
|
|
12
|
+
export { Card } from './Card.js';
|
|
13
|
+
export type { CardElement, CardPadding, CardProps } from './Card.js';
|
|
14
|
+
export { DangerButton } from './DangerButton.js';
|
|
15
|
+
export type { DangerButtonProps } from './DangerButton.js';
|
|
16
|
+
export { SubtleButton } from './SubtleButton.js';
|
|
17
|
+
export type { SubtleButtonProps } from './SubtleButton.js';
|
|
18
|
+
export type { CalendarBaseProps, CalendarDayState, CalendarLabels, CalendarProps, CalendarRangePosition, CalendarRangeProps, CalendarSingleProps, DateRangeDraft, } from './date/Calendar.js';
|
|
19
|
+
export { DatePicker } from './date/DatePicker.js';
|
|
20
|
+
export type { DatePickerLabels, DatePickerProps } from './date/DatePicker.js';
|
|
21
|
+
export { DateRangePicker } from './date/DateRangePicker.js';
|
|
22
|
+
export type { DateRangePickerLabels, DateRangePickerProps, DateRangePreset } from './date/DateRangePicker.js';
|
|
23
|
+
export { DateField, DateRangeField, TimeField } from './date/fields.js';
|
|
24
|
+
export type { DateFieldProps, DateRangeFieldProps, FieldLabels, TimeFieldProps } from './date/fields.js';
|
|
25
|
+
export { TimePicker } from './date/TimePicker.js';
|
|
26
|
+
export type { MinuteStep, TimePickerLabels, TimePickerProps } from './date/TimePicker.js';
|
|
27
|
+
export type { DateRange, IsoDate, IsoMonth, IsoTime, WeekStart } from './date/date.js';
|
|
28
|
+
export { Empty } from './Empty.js';
|
|
29
|
+
export type { EmptyProps, EmptyStatus } from './Empty.js';
|
|
30
|
+
export { Mark } from './Mark.js';
|
|
31
|
+
export type { MarkKind, MarkProps, MarkSize } from './Mark.js';
|
|
32
|
+
export { MessageProvider, useMessage } from './Message.js';
|
|
33
|
+
export type { MessageApi, MessageClose, MessageOptions, MessageProviderProps, MessageType } from './Message.js';
|
|
34
|
+
export { Pagination, pageItems } from './Pagination.js';
|
|
35
|
+
export type { PaginationItem, PaginationLabels, PaginationProps } from './Pagination.js';
|
|
36
|
+
export { QrCode } from './qr/QrCode.js';
|
|
37
|
+
export type { QrCodeProps } from './qr/QrCode.js';
|
|
38
|
+
export { Spinner } from './Spinner.js';
|
|
39
|
+
export type { SpinnerProps, SpinnerSize, SpinnerTone } from './Spinner.js';
|
|
40
|
+
export { StatusBadge } from './StatusBadge.js';
|
|
41
|
+
export type { StatusBadgeProps, StatusTone } from './StatusBadge.js';
|
|
42
|
+
export { Switch } from './Switch.js';
|
|
43
|
+
export type { SwitchProps, SwitchSize } from './Switch.js';
|
|
44
|
+
export { Tabs } from './Tabs.js';
|
|
45
|
+
export type { TabItem, TabsProps } from './Tabs.js';
|
|
46
|
+
export { Timeline } from './Timeline.js';
|
|
47
|
+
export type { TimelineGroup, TimelineItem, TimelineProps, TimelineStatus } from './Timeline.js';
|
|
48
|
+
export { Upload } from './Upload.js';
|
|
49
|
+
export type { UploadItem, UploadLabels, UploadLayout, UploadProps, UploadRejection, UploadRejectReason, UploadStatus, } from './Upload.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 把 QR 矩阵画成一张 SVG。
|
|
3
|
+
*
|
|
4
|
+
* 画法上两个取舍:
|
|
5
|
+
* - **一条 `path` 画完所有黑块**,而不是每个模块一个 `rect`:版本 20 有 9409 个模块,
|
|
6
|
+
* 铺成近万个节点会让弹窗肉眼可见地卡一下;
|
|
7
|
+
* - **留 4 个模块的静区**(规范要求),否则贴着深色背景的码扫不出来。
|
|
8
|
+
*
|
|
9
|
+
* **编码在组件内做**:聚合入口只许转发(`dist/seekbuddy.js` 不能自带运行时代码),
|
|
10
|
+
* 所以纯函数 `encodeQr` 不对外导出,调用方给文本、拿图。编不出来(空串或超出版本 20)时
|
|
11
|
+
* 渲染 `fallback`——典型是一条明文链接,宁可退回链接也不画一张扫不出来的码。
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { type ReactNode } from 'react';
|
|
16
|
+
/**
|
|
17
|
+
* QrCode 属性契约
|
|
18
|
+
*/
|
|
19
|
+
export interface QrCodeProps {
|
|
20
|
+
/** Text to encode (byte mode, up to 666 bytes). */
|
|
21
|
+
text: string;
|
|
22
|
+
/** Accessible name of the image; localized by the caller. */
|
|
23
|
+
label: string;
|
|
24
|
+
/** Rendered instead when the text cannot be encoded (empty or too long), typically the link as text. Renders nothing when omitted. */
|
|
25
|
+
fallback?: ReactNode | undefined;
|
|
26
|
+
/** Edge length in px. Default 180. */
|
|
27
|
+
size?: number | undefined;
|
|
28
|
+
/** Extra class on the root element, for layout. */
|
|
29
|
+
className?: string | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* QR code drawn as a single-path SVG with a 4-module quiet zone, black on white in both themes
|
|
33
|
+
* (scanners need the contrast, so no theme tokens). Encodes in byte mode at error-correction
|
|
34
|
+
* level M, versions 1–20. Text that cannot be encoded (empty, or over 666 bytes) renders
|
|
35
|
+
* `fallback` instead.
|
|
36
|
+
*/
|
|
37
|
+
export declare function QrCode({ text, label, fallback, size, className }: QrCodeProps): string | number | boolean | import("react").JSX.Element | Iterable<ReactNode> | null;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 最小 QR 编码器:把一段文本编成 QR 的模块矩阵,纯函数、无依赖、不碰 DOM。
|
|
3
|
+
*
|
|
4
|
+
* **为什么自己写而不是装一个库**:扩展组件会被使用方整份打进浏览器包;
|
|
5
|
+
* 现成的 QR 库要么带 canvas / fs 这类 Node 面(`qrcode` 就是),要么整包拉进来只为画一张码。
|
|
6
|
+
* 而要画的东西非常单一——一段链接——把编码规则直接写下来更省也更可控。
|
|
7
|
+
*
|
|
8
|
+
* **刻意收窄的范围**(够用即止,超出范围时返回 null,由调用方退回纯链接):
|
|
9
|
+
* - 只做 **byte 模式**:要编的是 URL,大小写混排,用不上 alphanumeric 那套省位;
|
|
10
|
+
* - 只做 **纠错等级 M**:屏幕上扫,15% 冗余足够,也让分块表只需要一列;
|
|
11
|
+
* - 只做 **版本 1–20**(≤666 字节):链接几百字符封顶,再长的码在屏幕上也难扫。
|
|
12
|
+
*
|
|
13
|
+
* 实现按 ISO/IEC 18004 的常规步骤:选版本 → 拼比特流 → 分块算 RS 纠错 → 交错 →
|
|
14
|
+
* 铺功能图形 → 之字形填数据 → 八种掩模挑罚分最低的 → 写格式信息(v≥7 再写版本信息)。
|
|
15
|
+
*
|
|
16
|
+
* 正确性不靠「看起来像个码」:`tests/qr.test.mjs` 拿 `qrcode` 这个成熟实现当参照物,
|
|
17
|
+
* 逐版本比对整张矩阵(版本、掩模、每一个模块都要一致)。分块表与对齐图形表写错会当场露出来。
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* 编码结果:正方形模块矩阵。
|
|
23
|
+
*/
|
|
24
|
+
export interface QrMatrix {
|
|
25
|
+
/** 边长(模块数) */
|
|
26
|
+
readonly size: number;
|
|
27
|
+
/** 行优先的模块,`true` 为黑 */
|
|
28
|
+
readonly modules: readonly boolean[];
|
|
29
|
+
/** 实际用到的版本号(1–20) */
|
|
30
|
+
readonly version: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 把文本编成 QR 矩阵(byte 模式,纠错等级 M)。
|
|
34
|
+
*
|
|
35
|
+
* @param text - 待编码文本(按 UTF-8 取字节)
|
|
36
|
+
* @returns 矩阵;空串或超出版本 20 的容量时返回 null(调用方退回纯链接)
|
|
37
|
+
*/
|
|
38
|
+
export declare function encodeQr(text: string): QrMatrix | null;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { DEFAULT_PREFERENCE, THEME_STORAGE_KEY } from './theme-core.js';
|
|
2
|
+
/** Inline this before application content in the root layout to avoid a saved-theme flash. */
|
|
3
|
+
export declare const THEME_BOOTSTRAP_SCRIPT = "(function(){try{var k='dsh-ui-primitives.theme-preference',v=localStorage.getItem(k);if(v!=='light'&&v!=='dark'&&v!=='system')v='system';var d=v==='dark'||(v==='system'&&matchMedia('(prefers-color-scheme: dark)').matches);document.documentElement.style.colorScheme=d?'dark':'light';document.body.toggleAttribute('data-ds-dark-theme',d)}catch(e){var d=matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.style.colorScheme=d?'dark':'light';document.body.toggleAttribute('data-ds-dark-theme',d)}})();";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const THEME_PREFERENCES: readonly ['light', 'dark', 'system'];
|
|
2
|
+
export type ThemePreference = (typeof THEME_PREFERENCES)[number];
|
|
3
|
+
export declare const DEFAULT_PREFERENCE: ThemePreference;
|
|
4
|
+
export declare const THEME_STORAGE_KEY = "dsh-ui-primitives.theme-preference";
|
|
5
|
+
type ThemeListener = () => void;
|
|
6
|
+
export declare function isThemePreference(value: unknown): value is ThemePreference;
|
|
7
|
+
export declare function resolveDark(preference: ThemePreference): boolean;
|
|
8
|
+
export declare function applyTheme(preference: ThemePreference): void;
|
|
9
|
+
export declare function initializeTheme(): ThemePreference;
|
|
10
|
+
export declare function setThemePreference(preference: ThemePreference): void;
|
|
11
|
+
export declare function getThemePreference(): ThemePreference;
|
|
12
|
+
export declare function getIsDark(): boolean;
|
|
13
|
+
export declare function subscribeTheme(listener: ThemeListener): () => void;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { DEFAULT_PREFERENCE, THEME_PREFERENCES, THEME_STORAGE_KEY, applyTheme, getIsDark, getThemePreference, initializeTheme, isThemePreference, resolveDark, setThemePreference, } from './theme-core.js';
|
|
2
|
+
export type { ThemePreference } from './theme-core.js';
|
|
3
|
+
export declare function useThemePreference(): "dark" | "light" | "system";
|
|
4
|
+
export declare function useIsDark(): boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Deterministic tooltip placement using measured border boxes and viewport coordinates. */
|
|
2
|
+
/** Bubble placement relative to the anchor. */
|
|
3
|
+
export type TooltipSide = 'right' | 'left' | 'bottom' | 'top';
|
|
4
|
+
interface PlacementInput {
|
|
5
|
+
anchor: {
|
|
6
|
+
left: number;
|
|
7
|
+
right: number;
|
|
8
|
+
top: number;
|
|
9
|
+
bottom: number;
|
|
10
|
+
};
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
viewportWidth: number;
|
|
14
|
+
viewportHeight: number;
|
|
15
|
+
side: TooltipSide;
|
|
16
|
+
align: 'center' | 'end';
|
|
17
|
+
gap: number;
|
|
18
|
+
}
|
|
19
|
+
interface TooltipPlacement {
|
|
20
|
+
left: number;
|
|
21
|
+
top: number;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
side: TooltipSide;
|
|
25
|
+
/** No complete side fits, so placement is bounded by the viewport instead. */
|
|
26
|
+
overflow: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Prefer the requested side, its opposite, then perpendicular sides without covering the anchor.
|
|
30
|
+
* @param input - Observed dimensions, anchor edges, viewport and requested placement; horizontal gaps remain 10px.
|
|
31
|
+
* @returns Border-box coordinates and the selected side; if no side fits, a viewport-bounded fallback.
|
|
32
|
+
*/
|
|
33
|
+
export declare function placeTooltip(input: PlacementInput): TooltipPlacement;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Clipboard action and its temporary success state. */
|
|
2
|
+
export interface ClipboardCopyState {
|
|
3
|
+
/** True for one second after an accepted clipboard write. */
|
|
4
|
+
readonly copied: boolean;
|
|
5
|
+
/** Write the current text unless a write or success indication is already active. */
|
|
6
|
+
readonly onCopy: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Keep clipboard feedback local to the mounted control and release its reset timer on unmount.
|
|
10
|
+
* @param text - Exact text to copy when the action is invoked.
|
|
11
|
+
* @returns Success feedback and a callback stable while text and feedback are unchanged.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useClipboardCopy(text: string): ClipboardCopyState;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Clamp a bottom-anchored overlay's max-height to the viewport.
|
|
4
|
+
* @param ref - the overlay element; a null current (overlay closed) skips measuring.
|
|
5
|
+
* @param cap - design max-height in px (the clamp never exceeds it).
|
|
6
|
+
* @param signal - re-measure trigger: pass the overlay's render state so anchor
|
|
7
|
+
* moves (composer growth) re-fit; resize/scroll re-fit while mounted.
|
|
8
|
+
* @param margin - viewport top margin floor in px; the frame's overlay
|
|
9
|
+
* inset widens it. Callers under fixed chrome (the conversation header)
|
|
10
|
+
* raise it past their chrome's height.
|
|
11
|
+
* @returns the max-height to apply inline, in px.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useAnchoredMaxHeight(ref: RefObject<HTMLElement | null>, cap: number, signal: unknown, margin?: number): number;
|