@crewlethq/ui 0.33.0 → 0.34.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 +18 -0
- package/dist/ArtifactBar/index.js +6 -4
- package/dist/ArtifactCard/ArtifactCard.d.ts +51 -11
- package/dist/ArtifactCard/index.d.ts +2 -2
- package/dist/ArtifactCard/index.js +3 -1
- package/dist/ArtifactCard-XHRLAL7C.css +289 -0
- package/dist/ArtifactCover/index.js +4 -2
- package/dist/ArtifactIcon/index.js +4 -2
- package/dist/ArtifactKindIllustration/ArtifactKindIllustration.d.ts +53 -0
- package/dist/ArtifactKindIllustration/index.d.ts +3 -0
- package/dist/ArtifactKindIllustration/index.js +3 -0
- package/dist/ArtifactKindIllustration-4NG6IE3C.css +211 -0
- package/dist/Canvas/index.js +2 -2
- package/dist/CanvasBoard/index.js +4 -4
- package/dist/CanvasToolbar/index.js +3 -3
- package/dist/ChangeMark/index.js +3 -3
- package/dist/FactList/index.js +2 -2
- package/dist/LivePreview/LivePreview.d.ts +83 -0
- package/dist/LivePreview/budget.d.ts +50 -0
- package/dist/LivePreview/index.d.ts +5 -0
- package/dist/LivePreview/index.js +2 -0
- package/dist/LivePreview-SRO7KHO4.css +65 -0
- package/dist/RichEditor/index.js +2 -2
- package/dist/SandboxedFrame/index.js +2 -2
- package/dist/Select/Select.d.ts +10 -0
- package/dist/Select/index.d.ts +1 -1
- package/dist/Select/index.js +1 -1
- package/dist/{Select-2P7AWUE4.css → Select-A54YS5EP.css} +29 -0
- package/dist/ShareDialog/index.js +2 -2
- package/dist/SheetGrid/SheetGrid.d.ts +4 -2
- package/dist/SheetGrid/index.js +4 -4
- package/dist/{SheetGrid-AKPUCK67.css → SheetGrid-GDPCCZ4V.css} +52 -11
- package/dist/SheetModel/index.js +1 -1
- package/dist/SheetModel/labels.d.ts +1 -1
- package/dist/Switcher/index.js +2 -2
- package/dist/TimeWindowPicker/index.js +2 -2
- package/dist/Tooltip/Tooltip.d.ts +12 -1
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.js +1 -1
- package/dist/TreeCanvas/index.js +3 -3
- package/dist/{chunk-22UEIXZE.js → chunk-3P4Y5RX6.js} +1 -1
- package/dist/{chunk-GLSOD5Z4.js → chunk-3Y56GQPM.js} +1 -1
- package/dist/{chunk-5FYPE5GL.js → chunk-6ZJ3N7QI.js} +5 -2
- package/dist/{chunk-2DHMVB5J.js → chunk-AORVEG5V.js} +1 -1
- package/dist/{chunk-UQGFHNDI.js → chunk-BQ7AKL2N.js} +3 -2
- package/dist/{chunk-ORT5IKHP.js → chunk-CCLNGVCM.js} +1 -1
- package/dist/{chunk-UNXLTJU7.js → chunk-CFAJP777.js} +1 -1
- package/dist/{chunk-G4ZW7A2W.js → chunk-EWAFN2IU.js} +33 -34
- package/dist/{chunk-7WHDPLVJ.js → chunk-HOIZ6MIS.js} +1 -1
- package/dist/{chunk-Z6GFMI2Z.js → chunk-IUD5VA2Z.js} +2 -2
- package/dist/chunk-KF6YGL4B.js +160 -0
- package/dist/{chunk-HH2GKAAE.js → chunk-PLDUNXAO.js} +1 -1
- package/dist/{chunk-ZNBLFCQS.js → chunk-SGHIAGPR.js} +2 -2
- package/dist/chunk-UDQW6UK7.js +129 -0
- package/dist/{chunk-4IJS5CPF.js → chunk-UHJQDFKQ.js} +1 -1
- package/dist/{chunk-J6ZSH3F5.js → chunk-VI5FWDZW.js} +2 -2
- package/dist/{chunk-MDNVHIB2.js → chunk-WPX6A5BV.js} +2 -2
- package/dist/chunk-XTOVADJU.js +170 -0
- package/dist/generated/index.d.ts +2 -0
- package/dist/generated/index.js +48 -46
- package/dist/index.js +48 -46
- package/dist/styles.css +544 -27
- package/package.json +3 -3
- package/dist/ArtifactCard-AS5Z4CVI.css +0 -124
- package/dist/chunk-DFZMYB5X.js +0 -108
- package/dist/{chunk-3U7S6ZUN.js → chunk-356JNSER.js} +1 -1
- package/dist/{chunk-MTMKIUWF.js → chunk-E4NNGC6X.js} +1 -1
- package/dist/{chunk-O37AQNLK.js → chunk-GMU6SQ6B.js} +1 -1
- /package/dist/{chunk-2JJIN6JN.js → chunk-YCARLYI6.js} +0 -0
|
@@ -194,25 +194,56 @@
|
|
|
194
194
|
box-shadow: 0 0 0 2px var(--crewlet-presence-hue);
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
/* THE GUTTER: one centred stack, so the number and the row's actions button
|
|
198
|
+
take exactly the same place and swapping one for the other moves nothing.
|
|
199
|
+
Its width is the component's fixed track (SHEET_ROW_NUMBER_WIDTH), which
|
|
200
|
+
holds five tabular digits, so row 9 and row 10000 stand in one column. */
|
|
197
201
|
.crewlet-sheet-grid__rownum {
|
|
202
|
+
display: grid;
|
|
203
|
+
grid-template-areas: 'gutter';
|
|
204
|
+
place-items: center;
|
|
198
205
|
color: var(--color-text-tertiary);
|
|
199
206
|
font-size: var(--font-size-xs);
|
|
200
207
|
font-variant-numeric: tabular-nums;
|
|
201
208
|
}
|
|
202
209
|
|
|
203
|
-
|
|
204
|
-
|
|
210
|
+
.crewlet-sheet-grid__rownum-number,
|
|
211
|
+
.crewlet-sheet-grid__row-actions {
|
|
212
|
+
grid-area: gutter;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/* THE ACTIONS BUTTON IS ALWAYS THERE, drawn clear until it is wanted, so a
|
|
216
|
+
tap on the number opens the row's menu on a screen with no pointer to
|
|
217
|
+
hover with. It shows, and the number gives way to it, under the pointer,
|
|
218
|
+
on the row holding focus (the active cell, or the button itself) and while
|
|
219
|
+
its menu is open. A row the reader has not entered keeps its number. */
|
|
205
220
|
.crewlet-sheet-grid__row-actions {
|
|
206
|
-
position: absolute;
|
|
207
|
-
top: 50%;
|
|
208
|
-
inset-inline-end: 0;
|
|
209
221
|
display: inline-flex;
|
|
210
|
-
|
|
222
|
+
opacity: 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.crewlet-sheet-grid__row:is(:hover, :focus-within) > .crewlet-sheet-grid__rownum > .crewlet-sheet-grid__row-actions,
|
|
226
|
+
.crewlet-sheet-grid__rownum--open > .crewlet-sheet-grid__row-actions {
|
|
227
|
+
opacity: 1;
|
|
211
228
|
}
|
|
212
229
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
230
|
+
.crewlet-sheet-grid__row:is(:hover, :focus-within) > .crewlet-sheet-grid__rownum--actions > .crewlet-sheet-grid__rownum-number,
|
|
231
|
+
.crewlet-sheet-grid__rownum--open > .crewlet-sheet-grid__rownum-number {
|
|
232
|
+
visibility: hidden;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* THE SELECTED ROWS' NUMBERS are marked as their cells are, and on the same
|
|
236
|
+
condition (the reader is in the grid, or the selection spans more than one
|
|
237
|
+
cell), the way a spreadsheet lights the row headers of a selection. The
|
|
238
|
+
tint is laid over the gutter's own ground, which a sticky gutter needs: a
|
|
239
|
+
translucent tint alone lets the values scrolling under it show through. */
|
|
240
|
+
.crewlet-sheet-grid__grid:is(:focus-within, .crewlet-sheet-grid__grid--range) .crewlet-sheet-grid__rownum--selected {
|
|
241
|
+
background: linear-gradient(var(--color-brand-accent-soft), var(--color-brand-accent-soft)) var(--color-surface-background);
|
|
242
|
+
color: var(--color-brand-accent-ink);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* The active cell's history is the reader's tool while they are in the grid,
|
|
246
|
+
not a mark on a sheet nobody has entered. */
|
|
216
247
|
.crewlet-sheet-grid__grid:not(:focus-within) .crewlet-sheet-grid__cell--history:not(:hover) > .crewlet-sheet-grid__history {
|
|
217
248
|
visibility: hidden;
|
|
218
249
|
}
|
|
@@ -255,9 +286,11 @@
|
|
|
255
286
|
/* THE SELECTION IS TINTED WHILE THE READER IS IN THE GRID, or while it
|
|
256
287
|
spans more than one cell. A grid nobody has entered still holds its first
|
|
257
288
|
cell as the active one (the keys start there), and tinting it drew a stray
|
|
258
|
-
highlight on every sheet as it opened.
|
|
289
|
+
highlight on every sheet as it opened. The tint is laid over the cell's
|
|
290
|
+
own ground: alone, a translucent tint on a frozen cell let the values
|
|
291
|
+
scrolling under it show through. */
|
|
259
292
|
.crewlet-sheet-grid__grid:is(:focus-within, .crewlet-sheet-grid__grid--range) .crewlet-sheet-grid__cell--selected {
|
|
260
|
-
background: var(--color-brand-accent-soft);
|
|
293
|
+
background: linear-gradient(var(--color-brand-accent-soft), var(--color-brand-accent-soft)) var(--color-surface-background);
|
|
261
294
|
}
|
|
262
295
|
|
|
263
296
|
/* THE FROZEN EDGE once the grid is scrolled sideways: the columns that stay
|
|
@@ -758,6 +791,14 @@
|
|
|
758
791
|
color: HighlightText;
|
|
759
792
|
}
|
|
760
793
|
|
|
794
|
+
/* A selected row's number takes the selection's ink on the page's ground:
|
|
795
|
+
on a Highlight ground the browser's backplate behind the digits drew
|
|
796
|
+
them as a solid block. */
|
|
797
|
+
.crewlet-sheet-grid__grid:is(:focus-within, .crewlet-sheet-grid__grid--range) .crewlet-sheet-grid__rownum--selected {
|
|
798
|
+
background: Canvas;
|
|
799
|
+
color: Highlight;
|
|
800
|
+
}
|
|
801
|
+
|
|
761
802
|
.crewlet-sheet-grid__rownum--present::before {
|
|
762
803
|
background: Highlight;
|
|
763
804
|
}
|
package/dist/SheetModel/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { LONGTEXT_MAX_DEFAULT, RATING_MAX_CEILING, RATING_MAX_DEFAULT, SHEET_COLUMN_BOUNDS, SHEET_COLUMN_TYPES, SHEET_COLUMN_WIDTHS, SHEET_FIT_SAMPLES, SHEET_LABELS, SHEET_ROW_HEIGHT, SHEET_ROW_NUMBER_WIDTH, SheetPendingEdits, TEXT_MAX_DEFAULT, URL_MAX, cellDescription, cellKey, cellSpeech, changeText, changeTime, checkValue, columnOffsets, columnWidth, compareValues, displayText, drawnColumns, editText, editorSide, findOption, findPerson, fitSamples, fittedWidth, flagText, hasPrevious, inRange, isEmptyValue, isMod, isMultiCell, isSheetColumnType, isTypingKey, liveOptions, moveFrom, nextSort, normalizeValue, optionHue, parseOptionList, parseTSV, parseText, planClear, planPaste, presenceByCell, presenceByColumn, presenceByRow, rangeOf, ratingMax, refusalText, rowName, sameValue, scrollToRow, sheetLabels, sortRows, spokenText, statusTone, textMax, toTSV, visibleRows } from '../chunk-
|
|
1
|
+
export { LONGTEXT_MAX_DEFAULT, RATING_MAX_CEILING, RATING_MAX_DEFAULT, SHEET_COLUMN_BOUNDS, SHEET_COLUMN_TYPES, SHEET_COLUMN_WIDTHS, SHEET_FIT_SAMPLES, SHEET_LABELS, SHEET_ROW_HEIGHT, SHEET_ROW_NUMBER_WIDTH, SheetPendingEdits, TEXT_MAX_DEFAULT, URL_MAX, cellDescription, cellKey, cellSpeech, changeText, changeTime, checkValue, columnOffsets, columnWidth, compareValues, displayText, drawnColumns, editText, editorSide, findOption, findPerson, fitSamples, fittedWidth, flagText, hasPrevious, inRange, isEmptyValue, isMod, isMultiCell, isSheetColumnType, isTypingKey, liveOptions, moveFrom, nextSort, normalizeValue, optionHue, parseOptionList, parseTSV, parseText, planClear, planPaste, presenceByCell, presenceByColumn, presenceByRow, rangeOf, ratingMax, refusalText, rowName, sameValue, scrollToRow, sheetLabels, sortRows, spokenText, statusTone, textMax, toTSV, visibleRows } from '../chunk-VI5FWDZW.js';
|
|
2
2
|
import '../chunk-Z7JYG5TF.js';
|
|
3
3
|
import '../chunk-AYKXMIOR.js';
|
|
@@ -59,7 +59,7 @@ export interface SheetLabels {
|
|
|
59
59
|
dismiss: string;
|
|
60
60
|
/** A refusal, as the grid announces it: "Not saved: <reason>". */
|
|
61
61
|
notSaved: (reason: string) => string;
|
|
62
|
-
/** The row actions
|
|
62
|
+
/** The row actions button in a row's number gutter (its name and tooltip), and its delete item. */
|
|
63
63
|
rowActions: (row: number) => string;
|
|
64
64
|
deleteRow: string;
|
|
65
65
|
/** Appended to the keyboard help when a row has actions. */
|
package/dist/Switcher/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export { Switcher } from '../chunk-
|
|
2
|
-
import '../chunk-TEUQWOWZ.js';
|
|
1
|
+
export { Switcher } from '../chunk-GMU6SQ6B.js';
|
|
3
2
|
import '../chunk-XEGZHHRH.js';
|
|
4
3
|
import '../chunk-F73MC7EZ.js';
|
|
5
4
|
import '../chunk-K3IJQNB7.js';
|
|
6
5
|
import '../chunk-FYTIJM2T.js';
|
|
7
6
|
import '../chunk-6QFAK2WV.js';
|
|
7
|
+
import '../chunk-TEUQWOWZ.js';
|
|
8
8
|
import '../chunk-PQADV6P6.js';
|
|
9
9
|
import '../chunk-RTPQDNW3.js';
|
|
10
10
|
import '../chunk-OMV5W53A.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
1
|
+
export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-AORVEG5V.js';
|
|
2
|
+
import '../chunk-BQ7AKL2N.js';
|
|
3
3
|
import '../chunk-F73MC7EZ.js';
|
|
4
4
|
import '../chunk-K3IJQNB7.js';
|
|
5
5
|
import '../chunk-GXQ3B46I.js';
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { type ReactElement, type ReactNode } from 'react';
|
|
2
2
|
export type TooltipPlacement = 'top' | 'bottom';
|
|
3
|
+
/**
|
|
4
|
+
* Where along the trigger the panel lines up: `center` on its middle, or
|
|
5
|
+
* `start` on its leading edge, running toward the inline end.
|
|
6
|
+
*/
|
|
7
|
+
export type TooltipAlign = 'center' | 'start';
|
|
3
8
|
export interface TooltipProps {
|
|
4
9
|
/** One short line. A tooltip is not a place to put a list or a paragraph. */
|
|
5
10
|
content: ReactNode;
|
|
6
11
|
/** The preferred side. It flips when there is not room and there is more room the other way. */
|
|
7
12
|
placement?: TooltipPlacement | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* `start` for a trigger at the leading edge of what it belongs to, such as a
|
|
15
|
+
* grid's row gutter: a centred tip there hangs past that edge, and at the
|
|
16
|
+
* page's edge is pushed off its trigger by the clamp.
|
|
17
|
+
*/
|
|
18
|
+
align?: TooltipAlign | undefined;
|
|
8
19
|
/** Nothing opens: for a trigger whose tip is only worth showing sometimes. */
|
|
9
20
|
disabled?: boolean | undefined;
|
|
10
21
|
/** Milliseconds a pointer rests on the trigger before the panel appears. Focus never waits. */
|
|
@@ -48,4 +59,4 @@ export interface TooltipProps {
|
|
|
48
59
|
* control has a name already, and replacing it with the hint is how a Close
|
|
49
60
|
* button came to be announced as "Closing is unavailable until this finishes".
|
|
50
61
|
*/
|
|
51
|
-
export declare function Tooltip({ content, placement, disabled, openDelay, closeDelay, className, children, }: TooltipProps): import("react").JSX.Element;
|
|
62
|
+
export declare function Tooltip({ content, placement, align, disabled, openDelay, closeDelay, className, children, }: TooltipProps): import("react").JSX.Element;
|
package/dist/Tooltip/index.d.ts
CHANGED
package/dist/Tooltip/index.js
CHANGED
package/dist/TreeCanvas/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { TreeCanvas } from '../chunk-
|
|
1
|
+
export { TreeCanvas } from '../chunk-UHJQDFKQ.js';
|
|
2
2
|
import '../chunk-MY374UUD.js';
|
|
3
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-3P4Y5RX6.js';
|
|
4
4
|
import '../chunk-LM3ISVJA.js';
|
|
5
5
|
import '../chunk-SMBKXWML.js';
|
|
6
|
-
import '../chunk-
|
|
6
|
+
import '../chunk-6ZJ3N7QI.js';
|
|
7
7
|
import '../chunk-OMV5W53A.js';
|
|
8
8
|
import '../chunk-R25RGPUB.js';
|
|
9
9
|
import '../chunk-OG6CL3EB.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LayerNodeBridge } from './chunk-LM3ISVJA.js';
|
|
2
2
|
import { Kbd } from './chunk-SMBKXWML.js';
|
|
3
|
-
import { Tooltip } from './chunk-
|
|
3
|
+
import { Tooltip } from './chunk-6ZJ3N7QI.js';
|
|
4
4
|
import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-OMV5W53A.js';
|
|
5
5
|
import { Button } from './chunk-OG6CL3EB.js';
|
|
6
6
|
import { IconButton } from './chunk-4FQT6ZAY.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Toolbar } from './chunk-PGRPNDWM.js';
|
|
2
|
-
import { ShortcutTip } from './chunk-
|
|
2
|
+
import { ShortcutTip } from './chunk-3P4Y5RX6.js';
|
|
3
3
|
import { IconButton } from './chunk-4FQT6ZAY.js';
|
|
4
4
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
5
5
|
import './CanvasToolbar-EM5EVZED.css';
|
|
@@ -28,6 +28,7 @@ var CLOSE_DELAY = ms(motion.duration.base);
|
|
|
28
28
|
function Tooltip({
|
|
29
29
|
content,
|
|
30
30
|
placement = "top",
|
|
31
|
+
align = "center",
|
|
31
32
|
disabled = false,
|
|
32
33
|
openDelay = OPEN_DELAY,
|
|
33
34
|
closeDelay = CLOSE_DELAY,
|
|
@@ -94,8 +95,10 @@ function Tooltip({
|
|
|
94
95
|
const host = inHost ? container.getBoundingClientRect() : viewportBounds();
|
|
95
96
|
const rect = at.getBoundingClientRect();
|
|
96
97
|
const own = box.getBoundingClientRect();
|
|
98
|
+
const rtl = getComputedStyle(at).direction === "rtl";
|
|
99
|
+
const startX = align === "center" ? rect.x + rect.width / 2 - own.width / 2 : rtl ? rect.right - own.width : rect.x;
|
|
97
100
|
const local = {
|
|
98
|
-
x:
|
|
101
|
+
x: startX - (inHost ? host.x : 0),
|
|
99
102
|
y: rect.y - (inHost ? host.y : 0),
|
|
100
103
|
width: rect.width,
|
|
101
104
|
height: rect.height
|
|
@@ -114,7 +117,7 @@ function Tooltip({
|
|
|
114
117
|
setPlace(
|
|
115
118
|
(was) => was && was.left === spot.left && was.top === spot.top && was.side === spot.side ? was : spot
|
|
116
119
|
);
|
|
117
|
-
}, [container, placement]);
|
|
120
|
+
}, [align, container, placement]);
|
|
118
121
|
useLayoutEffect(() => {
|
|
119
122
|
if (!open) return;
|
|
120
123
|
position();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Select } from './chunk-
|
|
1
|
+
import { Select } from './chunk-BQ7AKL2N.js';
|
|
2
2
|
import { Popover } from './chunk-K3IJQNB7.js';
|
|
3
3
|
import { today, shiftMonth, CalendarGrid, compareDays } from './chunk-GXQ3B46I.js';
|
|
4
4
|
import { Input } from './chunk-6QFAK2WV.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useListbox, useOptionKeys, useHighlightRest } from './chunk-F73MC7EZ.js';
|
|
2
2
|
import { useLayerContainer, viewportBounds, anchorGone, placePopup, LAYER_GAP, LAYER_REPOSITION_EVENT } from './chunk-OMV5W53A.js';
|
|
3
3
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
4
|
-
import './Select-
|
|
4
|
+
import './Select-A54YS5EP.css';
|
|
5
5
|
import { forwardRef, useId, useMemo, useState, useRef, useCallback, useEffect, useLayoutEffect } from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import { ChevronDownGlyph, CheckGlyph, SearchGlyph } from '@crewlethq/icons/glyphs';
|
|
@@ -24,6 +24,7 @@ var Select = forwardRef(function Select2({
|
|
|
24
24
|
align = "left",
|
|
25
25
|
active = false,
|
|
26
26
|
error = false,
|
|
27
|
+
appearance = "field",
|
|
27
28
|
ariaLabel,
|
|
28
29
|
searchable = false,
|
|
29
30
|
searchPlaceholder = "Search",
|
|
@@ -37,7 +38,7 @@ var Select = forwardRef(function Select2({
|
|
|
37
38
|
}, ref) {
|
|
38
39
|
const generatedId = useId();
|
|
39
40
|
const rootId = id ?? generatedId;
|
|
40
|
-
const classes = cx(className, width === "auto" && "crewlet-select--auto");
|
|
41
|
+
const classes = cx(className, width === "auto" && "crewlet-select--auto", appearance === "quiet" && "crewlet-select--quiet");
|
|
41
42
|
const chosen = useMemo(() => {
|
|
42
43
|
if (multiple) return Array.isArray(value) ? value : [];
|
|
43
44
|
if (value === void 0 || value === null) return [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Document } from './chunk-TYKQ33CL.js';
|
|
2
|
-
import { ArtifactKindGlyph } from './chunk-
|
|
2
|
+
import { ArtifactKindGlyph } from './chunk-XTOVADJU.js';
|
|
3
3
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
4
4
|
import './ArtifactCover-D4MBEJ5H.css';
|
|
5
5
|
import './DashboardCover-KYGYMRKW.css';
|
|
@@ -3,16 +3,18 @@ import { Tag } from './chunk-GFV4LJHH.js';
|
|
|
3
3
|
import { StatusDot } from './chunk-WIATRXEJ.js';
|
|
4
4
|
import { CursorFlag } from './chunk-3BYIWOTV.js';
|
|
5
5
|
import { presenceHueClass } from './chunk-I6POAB4V.js';
|
|
6
|
-
import { ChangeMark } from './chunk-
|
|
7
|
-
import { isEmptyValue, displayText, ratingMax, findPerson, findOption, statusTone, editText, textMax, sheetLabels, normalizeValue, sameValue, spokenText, drawnColumns, fitSamples, fittedWidth, columnWidth, SHEET_COLUMN_BOUNDS, sortRows, SHEET_ROW_HEIGHT, cellKey, columnOffsets, SHEET_ROW_NUMBER_WIDTH, rangeOf, presenceByCell, presenceByRow, presenceByColumn, scrollToRow, planClear, visibleRows, cellDescription, nextSort, rowName, inRange, hasPrevious, flagText, toTSV, planPaste, parseTSV, isMod, moveFrom, isTypingKey, editorSide, optionHue, parseText, liveOptions, checkValue } from './chunk-
|
|
6
|
+
import { ChangeMark } from './chunk-SGHIAGPR.js';
|
|
7
|
+
import { isEmptyValue, displayText, ratingMax, findPerson, findOption, statusTone, editText, textMax, sheetLabels, normalizeValue, sameValue, spokenText, drawnColumns, fitSamples, fittedWidth, columnWidth, SHEET_COLUMN_BOUNDS, sortRows, SHEET_ROW_HEIGHT, cellKey, columnOffsets, SHEET_ROW_NUMBER_WIDTH, rangeOf, presenceByCell, presenceByRow, presenceByColumn, scrollToRow, planClear, visibleRows, cellDescription, nextSort, rowName, inRange, hasPrevious, flagText, toTSV, planPaste, parseTSV, isMod, moveFrom, isTypingKey, editorSide, optionHue, parseText, liveOptions, checkValue } from './chunk-VI5FWDZW.js';
|
|
8
8
|
import { presenceLabels } from './chunk-Z7JYG5TF.js';
|
|
9
|
+
import { Tooltip } from './chunk-6ZJ3N7QI.js';
|
|
9
10
|
import { Avatar } from './chunk-PZKHBB7D.js';
|
|
10
11
|
import { Menu } from './chunk-3EB2AV3H.js';
|
|
11
12
|
import { isComposing } from './chunk-R25RGPUB.js';
|
|
12
13
|
import { Button } from './chunk-OG6CL3EB.js';
|
|
14
|
+
import { IconButton } from './chunk-4FQT6ZAY.js';
|
|
13
15
|
import { VisuallyHidden } from './chunk-BZFWDIV6.js';
|
|
14
16
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
15
|
-
import './SheetGrid-
|
|
17
|
+
import './SheetGrid-GDPCCZ4V.css';
|
|
16
18
|
import { useId, useRef, useMemo, useState, useLayoutEffect, useEffect, useCallback } from 'react';
|
|
17
19
|
import { CheckGlyph, StarGlyph, CircleAlertGlyph, ArrowUpGlyph, ArrowDownGlyph, TrashGlyph, EllipsisGlyph, RotateCcwClockGlyph, PlusGlyph } from '@crewlethq/icons/glyphs';
|
|
18
20
|
import { isCrewletCharacter } from '@crewlethq/icons/characters';
|
|
@@ -720,7 +722,6 @@ function SheetGrid({
|
|
|
720
722
|
const [local, setLocal] = useState(/* @__PURE__ */ new Map());
|
|
721
723
|
const [announcement, setAnnouncement] = useState({ text: "", n: 0 });
|
|
722
724
|
const dragging = useRef(false);
|
|
723
|
-
const [hoveredRow, setHoveredRow] = useState(null);
|
|
724
725
|
const [rowMenu, setRowMenu] = useState(null);
|
|
725
726
|
const say = useCallback((text) => setAnnouncement((current2) => ({ text, n: current2.n + 1 })), []);
|
|
726
727
|
const heardRefusals = useRef(/* @__PURE__ */ new Map());
|
|
@@ -1003,6 +1004,7 @@ function SheetGrid({
|
|
|
1003
1004
|
const page = Math.max(1, Math.floor(Math.max(viewport - headerHeight, rowHeight) / rowHeight) - 1);
|
|
1004
1005
|
const onKeyDown = (event) => {
|
|
1005
1006
|
if (editing || isComposing(event) || !current || !currentCell) return;
|
|
1007
|
+
if (event.target.closest(".crewlet-sheet-grid__row-actions")) return;
|
|
1006
1008
|
const column = columns[current.col];
|
|
1007
1009
|
const mod = isMod(event);
|
|
1008
1010
|
if (mod && event.altKey && event.key.toLowerCase() === "h") {
|
|
@@ -1191,11 +1193,6 @@ function SheetGrid({
|
|
|
1191
1193
|
className: cx("crewlet-sheet-grid__grid", range && (range.top !== range.bottom || range.left !== range.right) && "crewlet-sheet-grid__grid--range"),
|
|
1192
1194
|
style,
|
|
1193
1195
|
onKeyDown,
|
|
1194
|
-
onMouseMove: rowActions ? (event) => {
|
|
1195
|
-
const over = event.target.closest("[data-row-id]")?.dataset["rowId"] ?? null;
|
|
1196
|
-
setHoveredRow((was) => was === over ? was : over);
|
|
1197
|
-
} : void 0,
|
|
1198
|
-
onMouseLeave: rowActions ? () => setHoveredRow(null) : void 0,
|
|
1199
1196
|
onCopy,
|
|
1200
1197
|
onCut,
|
|
1201
1198
|
onPaste,
|
|
@@ -1248,6 +1245,9 @@ function SheetGrid({
|
|
|
1248
1245
|
/* @__PURE__ */ jsx("div", { role: "rowgroup", className: "crewlet-sheet-grid__body", style: { height: `${rows.length * rowHeight}px` }, children: drawn.map((index) => {
|
|
1249
1246
|
const row = rows[index];
|
|
1250
1247
|
const rowPresence = onRows.get(row.id);
|
|
1248
|
+
const rowNameId = `${id}-r${index}-name`;
|
|
1249
|
+
const rowSelected = range !== null && index >= range.top && index <= range.bottom;
|
|
1250
|
+
const actionsLabel = labels.rowActions(index + 1);
|
|
1251
1251
|
return /* @__PURE__ */ jsxs(
|
|
1252
1252
|
"div",
|
|
1253
1253
|
{
|
|
@@ -1262,43 +1262,42 @@ function SheetGrid({
|
|
|
1262
1262
|
{
|
|
1263
1263
|
role: "rowheader",
|
|
1264
1264
|
"aria-colindex": 1,
|
|
1265
|
+
"aria-labelledby": rowNameId,
|
|
1265
1266
|
className: cx(
|
|
1266
1267
|
"crewlet-sheet-grid__rownum",
|
|
1267
1268
|
lastFrozen < 0 && "crewlet-sheet-grid__frozen-edge",
|
|
1269
|
+
rowActions && "crewlet-sheet-grid__rownum--actions",
|
|
1270
|
+
rowSelected && "crewlet-sheet-grid__rownum--selected",
|
|
1271
|
+
rowMenu === row.id && "crewlet-sheet-grid__rownum--open",
|
|
1268
1272
|
rowPresence && "crewlet-sheet-grid__rownum--present",
|
|
1269
1273
|
rowPresence && presenceHueClass(rowPresence.hue)
|
|
1270
1274
|
),
|
|
1271
1275
|
children: [
|
|
1272
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: index + 1 }),
|
|
1273
|
-
/* @__PURE__ */ jsx(VisuallyHidden, { children: rowName(columns, row, index, context) }),
|
|
1274
|
-
rowActions
|
|
1275
|
-
|
|
1276
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-sheet-grid__rownum-number", "aria-hidden": "true", children: index + 1 }),
|
|
1277
|
+
/* @__PURE__ */ jsx(VisuallyHidden, { id: rowNameId, children: rowName(columns, row, index, context) }),
|
|
1278
|
+
rowActions ? /* @__PURE__ */ jsx("span", { className: "crewlet-sheet-grid__row-actions", children: /* @__PURE__ */ jsx(
|
|
1279
|
+
Menu,
|
|
1276
1280
|
{
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1281
|
+
label: actionsLabel,
|
|
1282
|
+
triggerTabIndex: -1,
|
|
1283
|
+
open: rowMenu === row.id,
|
|
1284
|
+
onOpenChange: (open) => setRowMenu(open ? row.id : null),
|
|
1285
|
+
renderTrigger: (trigger) => (
|
|
1286
|
+
// Lined up with the button's leading edge: the gutter is the
|
|
1287
|
+
// grid's first column, and a centred tip hung past the grid.
|
|
1288
|
+
/* @__PURE__ */ jsx(Tooltip, { content: actionsLabel, align: "start", children: /* @__PURE__ */ jsx(IconButton, { ...trigger, label: actionsLabel, icon: /* @__PURE__ */ jsx(EllipsisGlyph, {}), size: "sm", title: "" }) })
|
|
1280
1289
|
),
|
|
1281
|
-
|
|
1282
|
-
Menu,
|
|
1290
|
+
items: [
|
|
1283
1291
|
{
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
items: [
|
|
1290
|
-
{
|
|
1291
|
-
key: "delete",
|
|
1292
|
-
label: labels.deleteRow,
|
|
1293
|
-
icon: /* @__PURE__ */ jsx(TrashGlyph, { size: "sm" }),
|
|
1294
|
-
danger: true,
|
|
1295
|
-
onSelect: () => onDeleteRow?.(row.id)
|
|
1296
|
-
}
|
|
1297
|
-
]
|
|
1292
|
+
key: "delete",
|
|
1293
|
+
label: labels.deleteRow,
|
|
1294
|
+
icon: /* @__PURE__ */ jsx(TrashGlyph, { size: "sm" }),
|
|
1295
|
+
danger: true,
|
|
1296
|
+
onSelect: () => onDeleteRow?.(row.id)
|
|
1298
1297
|
}
|
|
1299
|
-
|
|
1298
|
+
]
|
|
1300
1299
|
}
|
|
1301
|
-
) : null
|
|
1300
|
+
) }) : null
|
|
1302
1301
|
]
|
|
1303
1302
|
}
|
|
1304
1303
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isApplePlatform, Kbd } from './chunk-SMBKXWML.js';
|
|
2
|
-
import { Tooltip } from './chunk-
|
|
2
|
+
import { Tooltip } from './chunk-6ZJ3N7QI.js';
|
|
3
3
|
import { SegmentedControl } from './chunk-CCAXYHQS.js';
|
|
4
|
-
import { ArtifactIcon } from './chunk-
|
|
4
|
+
import { ArtifactIcon } from './chunk-PLDUNXAO.js';
|
|
5
5
|
import { Menu } from './chunk-3EB2AV3H.js';
|
|
6
6
|
import { Button } from './chunk-OG6CL3EB.js';
|
|
7
7
|
import { IconButton } from './chunk-4FQT6ZAY.js';
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { cx } from './chunk-ODEQTPFM.js';
|
|
2
|
+
import './LivePreview-SRO7KHO4.css';
|
|
3
|
+
import { createContext, useMemo, useContext, useRef, useState, useEffect, useLayoutEffect } from 'react';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/LivePreview/budget.ts
|
|
7
|
+
var LIVE_PREVIEW_MAX = 12;
|
|
8
|
+
var immediately = (run) => {
|
|
9
|
+
run();
|
|
10
|
+
return () => {
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
var perFrame = (run) => {
|
|
14
|
+
if (typeof requestAnimationFrame === "undefined") return immediately(run);
|
|
15
|
+
let timer;
|
|
16
|
+
const frame = requestAnimationFrame(() => {
|
|
17
|
+
timer = setTimeout(run, 0);
|
|
18
|
+
});
|
|
19
|
+
return () => {
|
|
20
|
+
cancelAnimationFrame(frame);
|
|
21
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
function createLivePreviewBudget(max = LIVE_PREVIEW_MAX, schedule = immediately) {
|
|
25
|
+
const held = /* @__PURE__ */ new Set();
|
|
26
|
+
const queue = [];
|
|
27
|
+
let pending = null;
|
|
28
|
+
const next = () => {
|
|
29
|
+
if (pending || held.size >= max || queue.length === 0) return;
|
|
30
|
+
let ran = false;
|
|
31
|
+
const cancel = schedule(() => {
|
|
32
|
+
ran = true;
|
|
33
|
+
pending = null;
|
|
34
|
+
const ask = queue.shift();
|
|
35
|
+
if (ask && held.size < max) {
|
|
36
|
+
held.add(ask.ticket);
|
|
37
|
+
ask.grant();
|
|
38
|
+
} else if (ask) {
|
|
39
|
+
queue.unshift(ask);
|
|
40
|
+
}
|
|
41
|
+
next();
|
|
42
|
+
});
|
|
43
|
+
if (!ran) pending = cancel;
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
max,
|
|
47
|
+
request(grant) {
|
|
48
|
+
const ticket = {};
|
|
49
|
+
queue.push({ ticket, grant });
|
|
50
|
+
next();
|
|
51
|
+
let done = false;
|
|
52
|
+
return () => {
|
|
53
|
+
if (done) return;
|
|
54
|
+
done = true;
|
|
55
|
+
if (held.delete(ticket)) {
|
|
56
|
+
next();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const at = queue.findIndex((a) => a.ticket === ticket);
|
|
60
|
+
if (at >= 0) queue.splice(at, 1);
|
|
61
|
+
if (queue.length === 0 && pending) {
|
|
62
|
+
pending();
|
|
63
|
+
pending = null;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
live: () => held.size,
|
|
68
|
+
waiting: () => queue.length
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
var LIVE_PREVIEW_DWELL_MS = 120;
|
|
72
|
+
var DefaultBudget = createLivePreviewBudget(LIVE_PREVIEW_MAX, perFrame);
|
|
73
|
+
var BudgetContext = createContext(DefaultBudget);
|
|
74
|
+
function LivePreviewBudgetProvider({ max = LIVE_PREVIEW_MAX, children }) {
|
|
75
|
+
const budget = useMemo(() => createLivePreviewBudget(max, perFrame), [max]);
|
|
76
|
+
return /* @__PURE__ */ jsx(BudgetContext.Provider, { value: budget, children });
|
|
77
|
+
}
|
|
78
|
+
var NOOP = { ready: () => {
|
|
79
|
+
}, fail: () => {
|
|
80
|
+
} };
|
|
81
|
+
var SignalContext = createContext(NOOP);
|
|
82
|
+
function useLivePreview() {
|
|
83
|
+
return useContext(SignalContext);
|
|
84
|
+
}
|
|
85
|
+
function LivePreview({ children, fallback, width, rootMargin = "200px 0px", disabled = false, dwellMs = LIVE_PREVIEW_DWELL_MS, onStateChange, className }) {
|
|
86
|
+
const budget = useContext(BudgetContext);
|
|
87
|
+
const box = useRef(null);
|
|
88
|
+
const [near, setNear] = useState(false);
|
|
89
|
+
const [state, setState] = useState("idle");
|
|
90
|
+
const [failed, setFailed] = useState(false);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const el = box.current;
|
|
93
|
+
if (!el || disabled || typeof IntersectionObserver === "undefined") return void 0;
|
|
94
|
+
const seen = new IntersectionObserver((entries) => setNear(entries.some((e) => e.isIntersecting)), { rootMargin });
|
|
95
|
+
seen.observe(el);
|
|
96
|
+
return () => seen.disconnect();
|
|
97
|
+
}, [disabled, rootMargin]);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!near || disabled || failed) {
|
|
100
|
+
setState(failed ? "failed" : "idle");
|
|
101
|
+
return void 0;
|
|
102
|
+
}
|
|
103
|
+
setState("waiting");
|
|
104
|
+
let granted = false;
|
|
105
|
+
let giveBack = () => {
|
|
106
|
+
};
|
|
107
|
+
const dwell = setTimeout(() => {
|
|
108
|
+
giveBack = budget.request(() => {
|
|
109
|
+
granted = true;
|
|
110
|
+
setState("live");
|
|
111
|
+
});
|
|
112
|
+
}, dwellMs);
|
|
113
|
+
return () => {
|
|
114
|
+
clearTimeout(dwell);
|
|
115
|
+
giveBack();
|
|
116
|
+
if (granted) setState("idle");
|
|
117
|
+
};
|
|
118
|
+
}, [near, disabled, failed, budget, dwellMs]);
|
|
119
|
+
useEffect(() => onStateChange?.(state), [state, onStateChange]);
|
|
120
|
+
const mounted = state === "live" || state === "ready";
|
|
121
|
+
const signals = useMemo(
|
|
122
|
+
() => ({
|
|
123
|
+
ready: () => setState((s) => s === "live" ? "ready" : s),
|
|
124
|
+
fail: () => setFailed(true)
|
|
125
|
+
}),
|
|
126
|
+
[]
|
|
127
|
+
);
|
|
128
|
+
return /* @__PURE__ */ jsxs("span", { ref: box, className: cx("crewlet-live-preview", className), "data-state": state, "aria-hidden": "true", children: [
|
|
129
|
+
/* @__PURE__ */ jsx("span", { className: "crewlet-live-preview__fallback", children: fallback }),
|
|
130
|
+
mounted ? /* @__PURE__ */ jsx("span", { className: "crewlet-live-preview__live", inert: true, children: /* @__PURE__ */ jsx(SignalContext.Provider, { value: signals, children: width === void 0 ? children : /* @__PURE__ */ jsx(PreviewScale, { width, children }) }) }) : null
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
function PreviewScale({ children, width, height, fit = "width" }) {
|
|
134
|
+
const box = useRef(null);
|
|
135
|
+
const [size, setSize] = useState(null);
|
|
136
|
+
useLayoutEffect(() => {
|
|
137
|
+
const el = box.current;
|
|
138
|
+
if (!el) return void 0;
|
|
139
|
+
const measure = () => {
|
|
140
|
+
const rect = el.getBoundingClientRect();
|
|
141
|
+
if (rect.width > 0) setSize((was) => was && was.w === rect.width && was.h === rect.height ? was : { w: rect.width, h: rect.height });
|
|
142
|
+
};
|
|
143
|
+
measure();
|
|
144
|
+
if (typeof ResizeObserver === "undefined") return void 0;
|
|
145
|
+
const watch = new ResizeObserver(measure);
|
|
146
|
+
watch.observe(el);
|
|
147
|
+
return () => watch.disconnect();
|
|
148
|
+
}, []);
|
|
149
|
+
let layer = { width, visibility: "hidden" };
|
|
150
|
+
if (size) {
|
|
151
|
+
const k = fit === "contain" && height ? Math.min(size.w / width, size.h / height) : size.w / width;
|
|
152
|
+
const h = height ?? size.h / k;
|
|
153
|
+
const left = fit === "contain" ? (size.w - width * k) / 2 : 0;
|
|
154
|
+
const top = fit === "contain" ? (size.h - h * k) / 2 : 0;
|
|
155
|
+
layer = { width, height: h, transform: `translate(${left}px, ${top}px) scale(${k})` };
|
|
156
|
+
}
|
|
157
|
+
return /* @__PURE__ */ jsx("span", { ref: box, className: "crewlet-preview-scale", children: /* @__PURE__ */ jsx("span", { className: "crewlet-preview-scale__layer", style: layer, children }) });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export { LIVE_PREVIEW_DWELL_MS, LIVE_PREVIEW_MAX, LivePreview, LivePreviewBudgetProvider, PreviewScale, createLivePreviewBudget, immediately, perFrame, useLivePreview };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArtifactKindGlyph } from './chunk-
|
|
1
|
+
import { ArtifactKindGlyph } from './chunk-XTOVADJU.js';
|
|
2
2
|
import { ShieldGlyph, ActivityGlyph, GaugeGlyph, PackageGlyph, FolderGlyph, ClockGlyph, DatabaseGlyph, Settings2Glyph, BookOpenGlyph, FlagGlyph, StarGlyph, WandSparklesGlyph, BugGlyph, TargetGlyph, ImageGlyph, CodeGlyph, CoinsGlyph, UserGlyph, UsersGlyph, ChartNoAxesGanttGlyph, SquareKanbanGlyph, ListChecksGlyph, ListGlyph, GlobeGlyph, CompassGlyph, FileTextGlyph, TableGlyph, CalendarGlyph, LayoutDashboardGlyph, ChartPieGlyph, ChartColumnGlyph } from '@crewlethq/icons/glyphs';
|
|
3
3
|
import { jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { changeText, sheetLabels } from './chunk-
|
|
2
|
-
import { Tooltip } from './chunk-
|
|
1
|
+
import { changeText, sheetLabels } from './chunk-VI5FWDZW.js';
|
|
2
|
+
import { Tooltip } from './chunk-6ZJ3N7QI.js';
|
|
3
3
|
import { cx } from './chunk-ODEQTPFM.js';
|
|
4
4
|
import './ChangeMark-3VMTW7MT.css';
|
|
5
5
|
import { jsx } from 'react/jsx-runtime';
|