anentrypoint-design 0.0.355 → 0.0.357
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.357",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -73,6 +73,32 @@ export function useLongPress(targetEl, callback, { ms = 500 } = {}) {
|
|
|
73
73
|
return () => { cancel(); evts.forEach(([k, fn]) => targetEl.removeEventListener(k, fn)); };
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// withBusy — run an async action with its triggering button disabled +
|
|
77
|
+
// busy-labelled, so a double-click/double-tap can't fire it twice and the
|
|
78
|
+
// user sees progress. Restores the button (label, disabled state,
|
|
79
|
+
// aria-busy) when the action settles, including on throw. Re-entry while
|
|
80
|
+
// already busy is dropped silently rather than queued. Mirrors docstudio's
|
|
81
|
+
// dom-busy.js withButtonBusy — agentgui's app.js has no equivalent anywhere,
|
|
82
|
+
// so every async-click handler (share/delete/retry/approve-deny) is
|
|
83
|
+
// currently unguarded against rapid repeat clicks firing the same mutating
|
|
84
|
+
// request twice.
|
|
85
|
+
export async function withBusy(btn, fn, busyLabel = '...') {
|
|
86
|
+
if (!btn) return fn();
|
|
87
|
+
if (btn.disabled) return; // already in flight -> drop the repeat
|
|
88
|
+
const prevHtml = btn.innerHTML;
|
|
89
|
+
const prevDisabled = btn.disabled;
|
|
90
|
+
btn.disabled = true;
|
|
91
|
+
btn.setAttribute('aria-busy', 'true');
|
|
92
|
+
if (busyLabel != null) btn.textContent = busyLabel;
|
|
93
|
+
try {
|
|
94
|
+
return await fn();
|
|
95
|
+
} finally {
|
|
96
|
+
btn.disabled = prevDisabled;
|
|
97
|
+
btn.removeAttribute('aria-busy');
|
|
98
|
+
btn.innerHTML = prevHtml;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
76
102
|
// Tooltip — single shared bubble appended to <body>.
|
|
77
103
|
let _tipEl = null, _tipFloat = null, _tipTimer = null, _tipId = 0;
|
|
78
104
|
function _hideTip() {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// SpreadsheetPreview — tabbed inline spreadsheet/CSV viewer, ported from
|
|
2
|
+
// docstudio's documents/xls-preview.js. The kit does no parsing (no SheetJS
|
|
3
|
+
// dependency): the host hands over an already-parsed `workbook` shape and
|
|
4
|
+
// this component only renders tabs + a table + loading/error/truncation
|
|
5
|
+
// states, reusing the existing Skeleton/Alert primitives rather than
|
|
6
|
+
// inventing new visual language.
|
|
7
|
+
|
|
8
|
+
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
9
|
+
import { Skeleton, Alert } from './content.js';
|
|
10
|
+
const h = webjsx.createElement;
|
|
11
|
+
|
|
12
|
+
const DEFAULT_MAX_ROWS = 500;
|
|
13
|
+
const DEFAULT_MAX_COLS = 80;
|
|
14
|
+
|
|
15
|
+
// workbook: { sheetNames: string[], sheets: { [name]: string[][] } }
|
|
16
|
+
export function SpreadsheetPreview({
|
|
17
|
+
workbook, activeSheet, onSheetChange,
|
|
18
|
+
maxRows = DEFAULT_MAX_ROWS, maxCols = DEFAULT_MAX_COLS,
|
|
19
|
+
truncated, loading, error, errorActionLabel = 'retry', onErrorAction,
|
|
20
|
+
key,
|
|
21
|
+
} = {}) {
|
|
22
|
+
if (loading) {
|
|
23
|
+
return h('div', { key, class: 'ds-sheet-preview is-loading' },
|
|
24
|
+
Skeleton({ height: '1.8em', width: '40%', label: 'loading spreadsheet' }),
|
|
25
|
+
Skeleton({ height: '14em', width: '100%' }));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (error) {
|
|
29
|
+
return h('div', { key, class: 'ds-sheet-preview is-error' },
|
|
30
|
+
Alert({
|
|
31
|
+
kind: 'error',
|
|
32
|
+
title: 'could not preview this file',
|
|
33
|
+
children: [String(error)],
|
|
34
|
+
}),
|
|
35
|
+
onErrorAction ? h('button', {
|
|
36
|
+
type: 'button', class: 'ds-sheet-preview-error-action', onclick: onErrorAction,
|
|
37
|
+
}, errorActionLabel) : null);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const sheetNames = (workbook && workbook.sheetNames) || [];
|
|
41
|
+
if (!sheetNames.length) {
|
|
42
|
+
return h('div', { key, class: 'ds-sheet-preview is-empty' }, 'no sheets found');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const active = activeSheet && sheetNames.includes(activeSheet) ? activeSheet : sheetNames[0];
|
|
46
|
+
const rowsRaw = (workbook.sheets && workbook.sheets[active]) || [];
|
|
47
|
+
|
|
48
|
+
const rowOverflow = rowsRaw.length > maxRows;
|
|
49
|
+
const rows = rowsRaw.slice(0, maxRows);
|
|
50
|
+
const colOverflow = rows.some((r) => Array.isArray(r) && r.length > maxCols);
|
|
51
|
+
const clampedRows = rows.map((r) => (Array.isArray(r) ? r.slice(0, maxCols) : r));
|
|
52
|
+
const isTruncated = truncated || rowOverflow || colOverflow;
|
|
53
|
+
|
|
54
|
+
const isNumeric = (v) => v !== '' && v != null && !isNaN(Number(v));
|
|
55
|
+
|
|
56
|
+
return h('div', { key, class: 'ds-sheet-preview' },
|
|
57
|
+
sheetNames.length > 1 ? h('div', {
|
|
58
|
+
class: 'ds-sheet-preview-tabbar', role: 'tablist', 'aria-label': 'sheets',
|
|
59
|
+
}, ...sheetNames.map((name) => h('button', {
|
|
60
|
+
key: name, type: 'button', role: 'tab',
|
|
61
|
+
'aria-selected': name === active ? 'true' : 'false',
|
|
62
|
+
tabindex: name === active ? '0' : '-1',
|
|
63
|
+
class: 'ds-sheet-preview-tab' + (name === active ? ' is-active' : ''),
|
|
64
|
+
onclick: () => onSheetChange && onSheetChange(name),
|
|
65
|
+
}, name))) : null,
|
|
66
|
+
isTruncated ? h('div', { class: 'ds-sheet-preview-truncated', role: 'status' },
|
|
67
|
+
'showing first ' + clampedRows.length + ' rows' + (colOverflow ? ' (columns truncated)' : '') + ' — full file has more data') : null,
|
|
68
|
+
h('div', { class: 'ds-sheet-preview-body' },
|
|
69
|
+
clampedRows.length === 0
|
|
70
|
+
? h('div', { class: 'ds-sheet-preview-empty' }, 'empty sheet')
|
|
71
|
+
: h('table', { class: 'ds-sheet-preview-table' },
|
|
72
|
+
h('thead', {}, h('tr', {},
|
|
73
|
+
...(clampedRows[0] || []).map((cell, i) => h('th', { key: i, scope: 'col' }, cell == null ? '' : String(cell))))),
|
|
74
|
+
h('tbody', {}, ...clampedRows.slice(1).map((row, ri) => h('tr', { key: ri },
|
|
75
|
+
...row.map((cell, ci) => h('td', {
|
|
76
|
+
key: ci, class: isNumeric(cell) ? 'num' : null,
|
|
77
|
+
}, cell == null ? '' : String(cell)))))))));
|
|
78
|
+
}
|
package/src/components.js
CHANGED
|
@@ -33,6 +33,8 @@ export {
|
|
|
33
33
|
|
|
34
34
|
export { ContextPane } from './components/context-pane.js';
|
|
35
35
|
|
|
36
|
+
export { SpreadsheetPreview } from './components/spreadsheet-preview.js';
|
|
37
|
+
|
|
36
38
|
export {
|
|
37
39
|
fileGlyph, fmtFileSize,
|
|
38
40
|
FileIcon, FileRow, FileGrid, FileSkeleton, sortFiles, FileToolbar, RootsPicker,
|
|
@@ -90,7 +92,7 @@ export {
|
|
|
90
92
|
export {
|
|
91
93
|
Tooltip, Popover, Dropdown, useLongPress, useFloating,
|
|
92
94
|
CommandPalette, EmojiPicker, BootOverlay, SettingsPopover,
|
|
93
|
-
AuthModal, VideoLightbox, PermissionMenu, ApprovalPrompt
|
|
95
|
+
AuthModal, VideoLightbox, PermissionMenu, ApprovalPrompt, withBusy
|
|
94
96
|
} from './components/overlay-primitives.js';
|
|
95
97
|
|
|
96
98
|
export {
|
|
@@ -385,3 +385,46 @@
|
|
|
385
385
|
.ds-avatar-sm { width: 24px; height: 24px; font-size: 10px; }
|
|
386
386
|
.ds-avatar-md { width: 36px; height: 36px; font-size: 12px; }
|
|
387
387
|
.ds-avatar-lg { width: 48px; height: 48px; font-size: 15px; }
|
|
388
|
+
|
|
389
|
+
/* SpreadsheetPreview — tabbed inline spreadsheet/CSV viewer (docstudio
|
|
390
|
+
xls-preview.js port). Tabs reuse the same neutral-at-rest pattern as
|
|
391
|
+
Table's sortable headers; the truncation banner is persistent and never
|
|
392
|
+
hides the table underneath. */
|
|
393
|
+
.ds-sheet-preview { display: flex; flex-direction: column; gap: var(--space-2, 8px); min-width: 0; }
|
|
394
|
+
.ds-sheet-preview-tabbar {
|
|
395
|
+
display: flex; gap: var(--space-1, 4px); overflow-x: auto; -webkit-overflow-scrolling: touch;
|
|
396
|
+
border-bottom: 1px solid var(--border, var(--bg-3));
|
|
397
|
+
}
|
|
398
|
+
.ds-sheet-preview-tab {
|
|
399
|
+
flex-shrink: 0; background: none; border: none; cursor: pointer;
|
|
400
|
+
padding: var(--space-1-5, 5px) var(--space-2-5, 10px);
|
|
401
|
+
font: inherit; color: var(--fg-3); border-bottom: 2px solid transparent;
|
|
402
|
+
}
|
|
403
|
+
.ds-sheet-preview-tab:hover { color: var(--fg); }
|
|
404
|
+
.ds-sheet-preview-tab:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: -2px; }
|
|
405
|
+
.ds-sheet-preview-tab.is-active { color: var(--fg); border-bottom-color: var(--accent-ink, var(--accent)); }
|
|
406
|
+
.ds-sheet-preview-truncated {
|
|
407
|
+
font-size: var(--fs-tiny, 12px); color: var(--fg-3);
|
|
408
|
+
padding: var(--space-1, 4px) var(--space-2, 8px);
|
|
409
|
+
background: var(--bg-2); border-radius: var(--r-1, 6px);
|
|
410
|
+
}
|
|
411
|
+
.ds-sheet-preview-body { overflow: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
|
|
412
|
+
.ds-sheet-preview-table { min-width: 100%; border-collapse: collapse; font-size: var(--fs-sm, 13px); }
|
|
413
|
+
.ds-sheet-preview-table th, .ds-sheet-preview-table td {
|
|
414
|
+
padding: var(--space-1-5, 5px) var(--space-2, 8px);
|
|
415
|
+
border-bottom: 1px solid var(--border, var(--bg-3));
|
|
416
|
+
text-align: left; white-space: nowrap;
|
|
417
|
+
}
|
|
418
|
+
.ds-sheet-preview-table thead th {
|
|
419
|
+
position: sticky; top: 0; background: var(--bg-2); color: var(--fg-3);
|
|
420
|
+
font-weight: 600; z-index: 1;
|
|
421
|
+
}
|
|
422
|
+
.ds-sheet-preview-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
|
|
423
|
+
.ds-sheet-preview-empty { padding: var(--space-3, 16px); color: var(--fg-3); }
|
|
424
|
+
.ds-sheet-preview-error-action {
|
|
425
|
+
align-self: flex-start; background: none; border: 1px solid var(--border, var(--bg-3));
|
|
426
|
+
border-radius: var(--r-1, 6px); padding: var(--space-1, 4px) var(--space-2-5, 10px);
|
|
427
|
+
font: inherit; color: var(--fg); cursor: pointer;
|
|
428
|
+
}
|
|
429
|
+
.ds-sheet-preview-error-action:hover { background: var(--bg-2); }
|
|
430
|
+
.ds-sheet-preview-error-action:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 2px; }
|