@astryx-vue/lab 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,6 +24,7 @@ Or pick single files: `@astryx-vue/lab/styles/stat.css`, `.../log-stream.css`, a
24
24
  | --- | --- |
25
25
  | `Stat` | KPI/metric display: label, big tabular value, optional sentiment-aware delta, description, trend slot. |
26
26
  | `CircularProgress` | Ring-shaped progress indicator, determinate or indeterminate. |
27
+ | `DiffViewer` | Read-only unified or split diff for one file, with inline highlighting. |
27
28
  | `InfoTip` | Small "i" button that reveals a tooltip on hover, keyboard focus, and tap. |
28
29
  | `SVGIcon` | CSS-variable-driven SVG icon with variations (linear, bold, twotone, bulk, broken), path roles, and mask-based gaps. |
29
30
  | `LogStream` | Streaming log viewer with level accents, expandable detail rows, follow-scroll tailing, and a terminal variant. |
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { VNodeChild } from "vue";
2
- import { FieldStatusInput, IconSize, PopoverPlacement } from "@astryx-vue/core";
2
+ import { FieldStatusInput, IconSize, PopoverPlacement, SyntaxThemeDefinition } from "@astryx-vue/core";
3
3
  //#region src/CircularProgress/types.d.ts
4
4
  /** Variants a theme can extend through declaration merging in TypeScript. */
5
5
  interface CircularProgressVariantMap {
@@ -63,28 +63,291 @@ interface CircularProgressProps {
63
63
  //#endregion
64
64
  //#region src/CircularProgress/CircularProgress.vue.d.ts
65
65
  declare var __VLS_1$1: {};
66
- type __VLS_Slots$3 = {} & {
66
+ type __VLS_Slots$4 = {} & {
67
67
  default?: (props: typeof __VLS_1$1) => any;
68
68
  };
69
- declare const __VLS_base$3: import("vue").DefineComponent<CircularProgressProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<CircularProgressProps> & Readonly<{}>, {
69
+ declare const __VLS_base$4: import("vue").DefineComponent<CircularProgressProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<CircularProgressProps> & Readonly<{}>, {
70
70
  value: number;
71
- size: CircularProgressSize;
72
71
  max: number;
73
72
  isLabelHidden: boolean;
74
73
  hasValueLabel: boolean;
75
74
  formatValueLabel: (value: number, max: number) => string;
75
+ size: CircularProgressSize;
76
76
  variant: keyof CircularProgressVariantMap;
77
77
  isIndeterminate: boolean;
78
78
  isDisabled: boolean;
79
79
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
80
+ declare const __VLS_export$9: __VLS_WithSlots$4<typeof __VLS_base$4, __VLS_Slots$4>;
81
+ declare const _default: typeof __VLS_export$9;
82
+ type __VLS_WithSlots$4<T, S> = T & {
83
+ new (): {
84
+ $slots: S;
85
+ };
86
+ };
87
+ //#endregion
88
+ //#region src/DiffViewer/diffTypes.d.ts
89
+ /**
90
+ * @file diffTypes.ts
91
+ * @input None (type-only module)
92
+ * @output DiffViewerFile, DiffViewerHunk, DiffViewerLine, DiffViewerLineKind,
93
+ * DiffViewerFileStatus, DiffViewerSide, DiffViewerLineRef
94
+ * @position Lab diff model; produced by parseUnifiedDiff / createDiffFile and
95
+ * consumed by DiffViewer
96
+ *
97
+ * 数据模型和上游 `@astryxdesign/lab` 的 DiffViewer 保持一致:一个 hunk 里的行
98
+ * 去掉开头 `+`/`-`/空格标记后,各自记录旧文件和新文件里的行号。
99
+ */
100
+ /** One line of a hunk: adds, removes, or keeps a line. */
101
+ type DiffViewerLineKind = 'added' | 'removed' | 'context';
102
+ /** How the file changed as a whole. */
103
+ type DiffViewerFileStatus = 'added' | 'deleted' | 'modified' | 'renamed';
104
+ /**
105
+ * Which version of the file a line number belongs to: `old` is the original
106
+ * (left in split view), `new` the changed version (right in split view).
107
+ */
108
+ type DiffViewerSide = 'old' | 'new';
109
+ /** One line of a hunk, without its leading `+`/`-`/space glyph. */
110
+ interface DiffViewerLine {
111
+ kind: DiffViewerLineKind;
112
+ /** The line's text with the diff glyph removed. */
113
+ content: string;
114
+ /** 1-based line number in the old file; `null` for an added line. */
115
+ oldLineNumber: number | null;
116
+ /** 1-based line number in the new file; `null` for a removed line. */
117
+ newLineNumber: number | null;
118
+ }
119
+ /** One `@@` hunk: a run of changed lines with their surrounding context. */
120
+ interface DiffViewerHunk {
121
+ /** The hunk header as written, e.g. `@@ -12,7 +12,9 @@ function save()`. */
122
+ header: string;
123
+ oldStart: number;
124
+ oldLines: number;
125
+ newStart: number;
126
+ newLines: number;
127
+ lines: DiffViewerLine[];
128
+ }
129
+ /** One file's changes. */
130
+ interface DiffViewerFile {
131
+ /** Path before the change; `null` when the file was added. */
132
+ oldPath: string | null;
133
+ /** Path after the change; `null` when the file was deleted. */
134
+ newPath: string | null;
135
+ status: DiffViewerFileStatus;
136
+ /** True when the patch reports a binary change with no line hunks. */
137
+ isBinary: boolean;
138
+ hunks: DiffViewerHunk[];
139
+ }
140
+ /**
141
+ * Identifies one rendered line for annotations and line-number clicks. Every
142
+ * line has exactly one ref, the same in unified and split view, so `side` +
143
+ * `lineNumber` is a stable anchor: an added line is `new`, a removed line is
144
+ * `old`, and a context line is `new`.
145
+ */
146
+ interface DiffViewerLineRef {
147
+ side: DiffViewerSide;
148
+ lineNumber: number;
149
+ line: DiffViewerLine;
150
+ hunkIndex: number;
151
+ }
152
+ //#endregion
153
+ //#region src/DiffViewer/createDiffFile.d.ts
154
+ interface CreateDiffFileOptions {
155
+ /** The original text. */
156
+ oldValue: string;
157
+ /** The changed text. */
158
+ newValue: string;
159
+ /**
160
+ * Path of the file on both sides. `oldPath` / `newPath` take precedence
161
+ * when they are given.
162
+ */
163
+ path?: string;
164
+ /** Path before the change; pass `null` to mark the file as added. */
165
+ oldPath?: string | null;
166
+ /** Path after the change; pass `null` to mark the file as deleted. */
167
+ newPath?: string | null;
168
+ /**
169
+ * Unchanged lines kept around each change. Changes closer together than
170
+ * twice this share one hunk. `NaN` falls back to the default.
171
+ * @default 3
172
+ */
173
+ contextLines?: number;
174
+ }
175
+ /**
176
+ * Compute a {@link DiffViewerFile} from two versions of a text, for callers
177
+ * that hold file contents rather than a patch.
178
+ *
179
+ * @example
180
+ * ```
181
+ * const file = createDiffFile({oldValue: before, newValue: after, path: 'src/app.ts'});
182
+ * <DiffViewer file={file} />
183
+ * ```
184
+ */
185
+ export declare function createDiffFile({ oldValue, newValue, path, oldPath: oldPathOption, newPath: newPathOption, contextLines }: CreateDiffFileOptions): DiffViewerFile;
186
+ //#endregion
187
+ //#region src/DiffViewer/types.d.ts
188
+ /** How hunks are laid out: one column, or old and new side by side. */
189
+ type DiffViewerViewMode = 'unified' | 'split';
190
+ /**
191
+ * How finely to highlight what changed inside a removed line and the added
192
+ * line that replaced it: by `word`, by `char`acter, or `none`.
193
+ */
194
+ type DiffViewerInlineHighlight = 'word' | 'char' | 'none';
195
+ interface DiffViewerProps {
196
+ /**
197
+ * The file to render. Build one with `parseUnifiedDiff(patch)` (one per file
198
+ * in the patch) or `createDiffFile({oldValue, newValue})`.
199
+ */
200
+ file: DiffViewerFile;
201
+ /**
202
+ * `unified` shows one column with removed lines above their replacements;
203
+ * `split` shows the old file on the left and the new file on the right,
204
+ * pairing each removed line with the added line that replaced it.
205
+ * @default 'unified'
206
+ */
207
+ viewMode?: DiffViewerViewMode;
208
+ /**
209
+ * Syntax-highlighting language. Defaults to one inferred from the file's
210
+ * extension; unknown extensions render as plain text.
211
+ */
212
+ language?: string;
213
+ /**
214
+ * Show the old and new line-number gutters.
215
+ * @default true
216
+ */
217
+ hasLineNumbers?: boolean;
218
+ /**
219
+ * Wrap long lines instead of scrolling them horizontally.
220
+ * @default false
221
+ */
222
+ isWrapped?: boolean;
223
+ /**
224
+ * Highlight the changed words (or characters) inside each removed line and
225
+ * the added line that replaced it. Lines that share nothing but whitespace
226
+ * get no inline highlight; the row tint already marks them.
227
+ * @default 'word'
228
+ */
229
+ inlineHighlight?: DiffViewerInlineHighlight;
230
+ /**
231
+ * Make the file header a disclosure that hides and shows the hunks. Needs a
232
+ * file path to name the control.
233
+ * @default true
234
+ */
235
+ isCollapsible?: boolean;
236
+ /** Controlled collapsed state. Pair with `collapsedChange`. */
237
+ isCollapsed?: boolean;
238
+ /**
239
+ * Initial collapsed state when uncontrolled.
240
+ * @default false
241
+ */
242
+ defaultIsCollapsed?: boolean;
243
+ /** Maximum height of the hunk area before it scrolls. */
244
+ maxHeight?: number | string;
245
+ /**
246
+ * Per-instance syntax theme. Without it the nearest `SyntaxTheme` or the
247
+ * theme's syntax colors apply.
248
+ */
249
+ syntaxTheme?: SyntaxThemeDefinition;
250
+ /** Accessible name for the scrollable hunk area. @default 'Diff' */
251
+ label?: string;
252
+ /**
253
+ * Render content in a full-width row under a line, e.g. review comments.
254
+ * Return `null` for lines with nothing to show. In split view the row sits
255
+ * under the line's own side.
256
+ */
257
+ renderLineAnnotation?: (ref: DiffViewerLineRef) => VNodeChild;
258
+ }
259
+ interface DiffViewerEmits {
260
+ /** The header disclosure was toggled; carries the next collapsed state. */
261
+ 'collapsedChange': [isCollapsed: boolean];
262
+ /** v-model:isCollapsed support. */
263
+ 'update:isCollapsed': [isCollapsed: boolean];
264
+ /**
265
+ * A line number was clicked. Only the number on the line's anchor side is a
266
+ * button, so a context line reports its new side.
267
+ */
268
+ 'lineNumberClick': [ref: DiffViewerLineRef, event: MouseEvent];
269
+ }
270
+ interface DiffViewerSlots {
271
+ /** Content at the end of the file header, e.g. a "Viewed" checkbox. */
272
+ headerEnd?: () => VNodeChild;
273
+ }
274
+ //#endregion
275
+ //#region src/DiffViewer/DiffViewer.vue.d.ts
276
+ type __VLS_Slots$3 = DiffViewerSlots;
277
+ declare const __VLS_base$3: import("vue").DefineComponent<DiffViewerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
278
+ collapsedChange: (isCollapsed: boolean) => any;
279
+ "update:isCollapsed": (isCollapsed: boolean) => any;
280
+ lineNumberClick: (ref: DiffViewerLineRef, event: MouseEvent) => any;
281
+ }, string, import("vue").PublicProps, Readonly<DiffViewerProps> & Readonly<{
282
+ onCollapsedChange?: ((isCollapsed: boolean) => any) | undefined;
283
+ "onUpdate:isCollapsed"?: ((isCollapsed: boolean) => any) | undefined;
284
+ onLineNumberClick?: ((ref: DiffViewerLineRef, event: MouseEvent) => any) | undefined;
285
+ }>, {
286
+ label: string;
287
+ maxHeight: string | number;
288
+ viewMode: DiffViewerViewMode;
289
+ language: string;
290
+ hasLineNumbers: boolean;
291
+ isWrapped: boolean;
292
+ inlineHighlight: DiffViewerInlineHighlight;
293
+ isCollapsible: boolean;
294
+ isCollapsed: boolean;
295
+ defaultIsCollapsed: boolean;
296
+ syntaxTheme: import("@astryx-vue/core").SyntaxThemeDefinition;
297
+ renderLineAnnotation: (ref: DiffViewerLineRef) => import("vue").VNodeChild;
298
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
80
299
  declare const __VLS_export$8: __VLS_WithSlots$3<typeof __VLS_base$3, __VLS_Slots$3>;
81
- declare const _default: typeof __VLS_export$8;
300
+ declare const _default$1: typeof __VLS_export$8;
82
301
  type __VLS_WithSlots$3<T, S> = T & {
83
302
  new (): {
84
303
  $slots: S;
85
304
  };
86
305
  };
87
306
  //#endregion
307
+ //#region src/DiffViewer/inlineDiff.d.ts
308
+ /**
309
+ * @file inlineDiff.ts
310
+ * @input Two lines of text: a removed line and the added line that replaced it
311
+ * @output Exports diffInlineRanges and InlineRange: the changed character
312
+ * ranges on each side, for word- or character-level highlighting
313
+ * @position Lab helper used by DiffViewer's inline change highlighting
314
+ *
315
+ * Finds the longest common subsequence of the two lines' tokens (words,
316
+ * whitespace runs and single punctuation characters, or single characters)
317
+ * and reports what falls outside it on each side. Pure and synchronous.
318
+ *
319
+ * SYNC: When modified, update:
320
+ * - /packages/lab/src/DiffViewer/inlineDiff.test.ts
321
+ * - /packages/lab/src/DiffViewer/DiffViewer.tsx (the caller)
322
+ */
323
+ /** Half-open `[start, end)` character range within one line. */
324
+ type InlineRange = readonly [start: number, end: number];
325
+ /** How finely to compare a pair of lines. */
326
+ type InlineDiffGranularity = 'word' | 'char';
327
+ interface InlineDiffResult {
328
+ /** Changed ranges in the removed (old) line. */
329
+ old: InlineRange[];
330
+ /** Changed ranges in the added (new) line. */
331
+ new: InlineRange[];
332
+ }
333
+ //#endregion
334
+ //#region src/DiffViewer/parseUnifiedDiff.d.ts
335
+ /**
336
+ * Parse a unified diff into one {@link DiffViewerFile} per file.
337
+ *
338
+ * Accepts `git diff` output (with `diff --git`, mode, rename, copy, and
339
+ * binary lines), classic `diff -u` output (`---`/`+++` pairs), several files in one
340
+ * patch, and a bare `@@` hunk with no file header (returned as one file with
341
+ * null paths). Input it cannot read yields `[]`; it never throws.
342
+ *
343
+ * @example
344
+ * ```
345
+ * const files = parseUnifiedDiff(patch);
346
+ * files.map((file) => <DiffViewer key={file.newPath ?? file.oldPath} file={file} />);
347
+ * ```
348
+ */
349
+ export declare function parseUnifiedDiff(patch: string): DiffViewerFile[];
350
+ //#endregion
88
351
  //#region src/InfoTip/types.d.ts
89
352
  /**
90
353
  * Size of the info icon. Maps 1:1 to core `Icon` sizes
@@ -119,7 +382,7 @@ declare const __VLS_base$2: import("vue").DefineComponent<InfoTipProps, {}, {},
119
382
  content: string;
120
383
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
121
384
  declare const __VLS_export$7: __VLS_WithSlots$2<typeof __VLS_base$2, __VLS_Slots$2>;
122
- declare const _default$1: typeof __VLS_export$7;
385
+ declare const _default$2: typeof __VLS_export$7;
123
386
  type __VLS_WithSlots$2<T, S> = T & {
124
387
  new (): {
125
388
  $slots: S;
@@ -249,7 +512,7 @@ declare const __VLS_export$6: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_
249
512
  }>) => import("vue").VNode & {
250
513
  __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
251
514
  };
252
- declare const _default$2: typeof __VLS_export$6;
515
+ declare const _default$3: typeof __VLS_export$6;
253
516
  type __VLS_PrettifyLocal$3<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {};
254
517
  //#endregion
255
518
  //#region src/LogStream/types.d.ts
@@ -335,7 +598,7 @@ declare const __VLS_base$1: import("vue").DefineComponent<__VLS_PublicProps, {},
335
598
  hasTimestamps: boolean;
336
599
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
337
600
  declare const __VLS_export$5: __VLS_WithSlots$1<typeof __VLS_base$1, __VLS_Slots$1>;
338
- declare const _default$3: typeof __VLS_export$5;
601
+ declare const _default$4: typeof __VLS_export$5;
339
602
  type __VLS_WithSlots$1<T, S> = T & {
340
603
  new (): {
341
604
  $slots: S;
@@ -426,7 +689,7 @@ declare const __VLS_export$4: <T extends SearchableItem>(__VLS_props: NonNullabl
426
689
  }>) => import("vue").VNode & {
427
690
  __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
428
691
  };
429
- declare const _default$4: typeof __VLS_export$4;
692
+ declare const _default$5: typeof __VLS_export$4;
430
693
  type __VLS_PrettifyLocal$2<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {};
431
694
  //#endregion
432
695
  //#region src/Stat/types.d.ts
@@ -473,12 +736,12 @@ type __VLS_Slots = {} & {
473
736
  };
474
737
  declare const __VLS_base: import("vue").DefineComponent<StatProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<StatProps> & Readonly<{}>, {
475
738
  value: string;
739
+ size: StatSize;
476
740
  delta: StatDelta;
477
741
  description: string;
478
- size: StatSize;
479
742
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
480
743
  declare const __VLS_export$3: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
481
- declare const _default$6: typeof __VLS_export$3;
744
+ declare const _default$7: typeof __VLS_export$3;
482
745
  type __VLS_WithSlots<T, S> = T & {
483
746
  new (): {
484
747
  $slots: S;
@@ -626,7 +889,7 @@ declare const __VLS_export$2: import("vue").DefineComponent<SVGIconProps, {}, {}
626
889
  variation: SVGIconVariation;
627
890
  color: SVGIconColor;
628
891
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
629
- declare const _default$5: typeof __VLS_export$2;
892
+ declare const _default$6: typeof __VLS_export$2;
630
893
  //#endregion
631
894
  //#region src/SVGIcon/types-xif.d.ts
632
895
  /**
@@ -850,7 +1113,7 @@ declare const __VLS_export$1: <T extends string>(__VLS_props: NonNullable<Awaite
850
1113
  }>) => import("vue").VNode & {
851
1114
  __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
852
1115
  };
853
- declare const _default$7: typeof __VLS_export$1;
1116
+ declare const _default$8: typeof __VLS_export$1;
854
1117
  type __VLS_PrettifyLocal$1<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {};
855
1118
  //#endregion
856
1119
  //#region src/TransferList/TransferListSelector.vue.d.ts
@@ -906,7 +1169,7 @@ declare const __VLS_export: <T extends string>(__VLS_props: NonNullable<Awaited<
906
1169
  }>) => import("vue").VNode & {
907
1170
  __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
908
1171
  };
909
- declare const _default$8: typeof __VLS_export;
1172
+ declare const _default$9: typeof __VLS_export;
910
1173
  type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {};
911
1174
  //#endregion
912
- export { _default as CircularProgress, type CircularProgressProps, type CircularProgressSize, type CircularProgressVariant, type CircularProgressVariantMap, type IconShape, type IconShapeRole, _default$1 as InfoTip, type InfoTipProps, type InfoTipSize, _default$2 as ListInput, type ListInputChange, type ListInputColumn, type ListInputColumnWidth, type ListInputEmits, type ListInputProps, type ListInputRenderContext, type ListInputValueContext, type LogEntry, _default$3 as LogStream, type LogStreamEmits, type LogStreamLevel, type LogStreamProps, _default$4 as MobileTokenizer, type MobileTokenizerChange, type MobileTokenizerEmits, type MobileTokenizerProps, type PanelGroup, type PanelRow, type PathPersonality, _default$5 as SVGIcon, type SVGIconColor, type SVGIconDef, type SVGIconProps, type SVGIconSize, type SVGIconVariation, type SearchSource, type SearchableItem, _default$6 as Stat, type StatDelta, type StatDeltaDirection, type StatDeltaSentiment, type StatProps, type StatSize, _default$7 as TransferList, type TransferListEmits, type TransferListOption, type TransferListProps, _default$8 as TransferListSelector, type TransferListSlots, type XIFAnimate, type XIFIcon, type XIFPath, type XIFPersonality, type XIFSlot };
1175
+ export { _default as CircularProgress, type CircularProgressProps, type CircularProgressSize, type CircularProgressVariant, type CircularProgressVariantMap, type CreateDiffFileOptions, _default$1 as DiffViewer, type DiffViewerEmits, type DiffViewerFile, type DiffViewerFileStatus, type DiffViewerHunk, type DiffViewerInlineHighlight, type DiffViewerLine, type DiffViewerLineKind, type DiffViewerLineRef, type DiffViewerProps, type DiffViewerSide, type DiffViewerSlots, type DiffViewerViewMode, type IconShape, type IconShapeRole, _default$2 as InfoTip, type InfoTipProps, type InfoTipSize, type InlineDiffGranularity, type InlineDiffResult, type InlineRange, _default$3 as ListInput, type ListInputChange, type ListInputColumn, type ListInputColumnWidth, type ListInputEmits, type ListInputProps, type ListInputRenderContext, type ListInputValueContext, type LogEntry, _default$4 as LogStream, type LogStreamEmits, type LogStreamLevel, type LogStreamProps, _default$5 as MobileTokenizer, type MobileTokenizerChange, type MobileTokenizerEmits, type MobileTokenizerProps, type PanelGroup, type PanelRow, type PathPersonality, _default$6 as SVGIcon, type SVGIconColor, type SVGIconDef, type SVGIconProps, type SVGIconSize, type SVGIconVariation, type SearchSource, type SearchableItem, _default$7 as Stat, type StatDelta, type StatDeltaDirection, type StatDeltaSentiment, type StatProps, type StatSize, _default$8 as TransferList, type TransferListEmits, type TransferListOption, type TransferListProps, _default$9 as TransferListSelector, type TransferListSlots, type XIFAnimate, type XIFIcon, type XIFPath, type XIFPersonality, type XIFSlot };