@react-x11/components 0.5.0 → 0.7.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 +67 -43
- package/dist/formula/node.d.ts.map +1 -1
- package/dist/formula/node.js +17 -6
- package/dist/formula/node.js.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/markdown/ast.d.ts +80 -6
- package/dist/markdown/ast.d.ts.map +1 -1
- package/dist/markdown/ast.js +13 -4
- package/dist/markdown/ast.js.map +1 -1
- package/dist/markdown/expressions.d.ts +27 -0
- package/dist/markdown/expressions.d.ts.map +1 -0
- package/dist/markdown/expressions.js +203 -0
- package/dist/markdown/expressions.js.map +1 -0
- package/dist/markdown/index.d.ts +61 -2
- package/dist/markdown/index.d.ts.map +1 -1
- package/dist/markdown/index.js +101 -2
- package/dist/markdown/index.js.map +1 -1
- package/dist/markdown/parse.d.ts +1 -1
- package/dist/markdown/parse.d.ts.map +1 -1
- package/dist/markdown/parse.js +163 -15
- package/dist/markdown/parse.js.map +1 -1
- package/dist/markdown/spans.d.ts.map +1 -1
- package/dist/markdown/spans.js +4 -0
- package/dist/markdown/spans.js.map +1 -1
- package/dist/markdown/tags.d.ts +35 -0
- package/dist/markdown/tags.d.ts.map +1 -0
- package/dist/markdown/tags.js +213 -0
- package/dist/markdown/tags.js.map +1 -0
- package/dist/richtext/node.d.ts.map +1 -1
- package/dist/richtext/node.js +7 -2
- package/dist/richtext/node.js.map +1 -1
- package/dist/table/index.d.ts +15 -0
- package/dist/table/index.d.ts.map +1 -1
- package/dist/table/index.js +95 -11
- package/dist/table/index.js.map +1 -1
- package/dist/tree/index.d.ts.map +1 -1
- package/dist/tree/index.js +77 -2
- package/dist/tree/index.js.map +1 -1
- package/package.json +4 -8
- package/src/formula/node.ts +22 -34
- package/src/index.ts +4 -18
- package/src/markdown/ast.ts +85 -9
- package/src/markdown/expressions.ts +223 -0
- package/src/markdown/index.ts +190 -5
- package/src/markdown/parse.ts +230 -15
- package/src/markdown/spans.ts +4 -0
- package/src/markdown/tags.ts +240 -0
- package/src/richtext/node.ts +7 -2
- package/src/table/index.ts +114 -10
- package/src/tree/index.ts +77 -2
- package/dist/desktop-calendar/eds.d.ts +0 -102
- package/dist/desktop-calendar/eds.d.ts.map +0 -1
- package/dist/desktop-calendar/eds.js +0 -356
- package/dist/desktop-calendar/eds.js.map +0 -1
- package/dist/desktop-calendar/ical.d.ts +0 -63
- package/dist/desktop-calendar/ical.d.ts.map +0 -1
- package/dist/desktop-calendar/ical.js +0 -57
- package/dist/desktop-calendar/ical.js.map +0 -1
- package/dist/desktop-calendar/index.d.ts +0 -72
- package/dist/desktop-calendar/index.d.ts.map +0 -1
- package/dist/desktop-calendar/index.js +0 -213
- package/dist/desktop-calendar/index.js.map +0 -1
- package/src/desktop-calendar/eds.ts +0 -484
- package/src/desktop-calendar/ical.ts +0 -119
- package/src/desktop-calendar/index.ts +0 -287
package/src/table/index.ts
CHANGED
|
@@ -136,6 +136,28 @@ const HALF = 3;
|
|
|
136
136
|
const GRIP = HALF + RULE + HALF;
|
|
137
137
|
/** What one Left/Right on a focused grip is worth. */
|
|
138
138
|
const STEP = 16;
|
|
139
|
+
/**
|
|
140
|
+
* How far the grid sits inside the table's own edge — the default `rowInset`.
|
|
141
|
+
*
|
|
142
|
+
* It is what makes a selection read as a **pill on** the list rather than a
|
|
143
|
+
* band across it. With no inset the wash runs into whatever the table is
|
|
144
|
+
* mounted against, and the selected row reads as a stripe cut across the pane
|
|
145
|
+
* instead of a mark on a row. Core's `Menu` insets its rows from the sheet
|
|
146
|
+
* for exactly this reason, and `MENU_PAD` is this number.
|
|
147
|
+
*
|
|
148
|
+
* **The inset is the grid's, not the row's**, which is where a table parts
|
|
149
|
+
* company with `<Tree>`. A tree row is alone in its pane, so its own margin
|
|
150
|
+
* is the whole story; a table row is one half of a grid whose other half is
|
|
151
|
+
* the header, and a margin on the row alone would slide every cell four
|
|
152
|
+
* pixels out from under the column it belongs to. So the body pane is padded
|
|
153
|
+
* and the header row is offset by the same amount, and the columns resolve
|
|
154
|
+
* into what is left — which is also why this is a prop rather than something
|
|
155
|
+
* `styles.row` could express (see `rowInset`).
|
|
156
|
+
*
|
|
157
|
+
* Horizontal only. Rows stack flush against each other: clearing the first
|
|
158
|
+
* and the last is the job of whatever the table is mounted in.
|
|
159
|
+
*/
|
|
160
|
+
const ROW_INSET = 4;
|
|
139
161
|
/**
|
|
140
162
|
* Where `virtual="auto"` starts virtualizing.
|
|
141
163
|
*
|
|
@@ -342,6 +364,21 @@ interface TableBaseProps<Row> extends Omit<
|
|
|
342
364
|
* the measure pass. `rowHeight={24}` restores core's exact behaviour.
|
|
343
365
|
*/
|
|
344
366
|
rowHeight?: number;
|
|
367
|
+
/**
|
|
368
|
+
* How far the grid sits inside the table's edge, in pixels. Default 4.
|
|
369
|
+
*
|
|
370
|
+
* It is what makes the selection and hover washes read as pills on the
|
|
371
|
+
* list rather than bands across it, and the row's corner radius follows
|
|
372
|
+
* it: `rowInset={0}` is the full-bleed, square-cornered band, because a
|
|
373
|
+
* pill has to be inset to be *seen* as one and rounding a full-bleed row
|
|
374
|
+
* only shows the pane through four notched corners.
|
|
375
|
+
*
|
|
376
|
+
* A prop rather than a `styles.row` margin because the header has to move
|
|
377
|
+
* with the body — see `ROW_INSET`. The columns resolve into the width this
|
|
378
|
+
* leaves, so widening it narrows the flex columns rather than starting a
|
|
379
|
+
* horizontal scroll.
|
|
380
|
+
*/
|
|
381
|
+
rowInset?: number;
|
|
345
382
|
/** What an unmeasured row is assumed — and floored — at, while measuring.
|
|
346
383
|
* Default 24. The scrollbar is this guess for every row not yet seen; it
|
|
347
384
|
* converges as you scroll, and once enough rows have been measured the
|
|
@@ -495,6 +532,10 @@ interface TableRowViewProps<Row> {
|
|
|
495
532
|
rowHeight: number | undefined;
|
|
496
533
|
estimate: number;
|
|
497
534
|
theme: Theme;
|
|
535
|
+
/** The row's corner, resolved once at the table level — see `rowRadius`
|
|
536
|
+
* there for why it is `radiusSmall` and not core's popup derivation. A
|
|
537
|
+
* number rather than a lookup so the memo still bails out on a scroll. */
|
|
538
|
+
radius: number;
|
|
498
539
|
rowStyle: TableStyles<Row>['row'];
|
|
499
540
|
cellStyle: TableStyles<Row>['cell'];
|
|
500
541
|
renderRow?: (state: TableRowState<Row>, content: ReactNode[]) => ReactNode;
|
|
@@ -522,6 +563,7 @@ function TableRowView<Row>(props: TableRowViewProps<Row>): ReactElement {
|
|
|
522
563
|
rowHeight,
|
|
523
564
|
estimate,
|
|
524
565
|
theme,
|
|
566
|
+
radius,
|
|
525
567
|
rowStyle,
|
|
526
568
|
cellStyle,
|
|
527
569
|
renderRow,
|
|
@@ -611,17 +653,32 @@ function TableRowView<Row>(props: TableRowViewProps<Row>): ReactElement {
|
|
|
611
653
|
selectable && { cursor: 'pointer' },
|
|
612
654
|
{
|
|
613
655
|
backgroundColor: isSelected ? theme.hoverBackground : 'transparent',
|
|
656
|
+
// A pill on the list rather than a band across it. The inset that
|
|
657
|
+
// makes it one is the grid's — see `ROW_INSET` — and this is the
|
|
658
|
+
// corner that goes with it.
|
|
659
|
+
borderRadius: radius,
|
|
614
660
|
// The row's ink, said once: `color` inherits, so default cells
|
|
615
661
|
// take it without being handed it.
|
|
616
662
|
color,
|
|
617
663
|
},
|
|
618
664
|
selectable && {
|
|
619
|
-
//
|
|
620
|
-
// is already
|
|
621
|
-
//
|
|
665
|
+
// The press marks the row it lands on, and the pressed colour comes
|
|
666
|
+
// from the ramp that row is already painted with. An unselected row is on the surface ramp, so it is
|
|
667
|
+
// `surfaceActive`. A selected row is washed with `hoverBackground`,
|
|
668
|
+
// and `accentActive` — what this used to say — is the pressed step
|
|
669
|
+
// of `accent`: a different token that merely *holds* the same
|
|
670
|
+
// colour in both stock palettes. Move the accent and the press
|
|
671
|
+
// flashes something the table never wears at rest; a yellow accent
|
|
672
|
+
// over a blue selection gives a yellow press, and the row's ink is
|
|
673
|
+
// still `hoverText`, picked to be legible on the blue. There is no
|
|
674
|
+
// darker step of `hoverBackground` in the palette to reach for and
|
|
675
|
+
// the selected row is already the strongest fill in the list, so
|
|
676
|
+
// it keeps its wash. That row is the one place a press shows
|
|
677
|
+
// nothing, and it is also the one row whose press already has an
|
|
678
|
+
// answer: it is selected, and a second click opens it.
|
|
622
679
|
':active': {
|
|
623
680
|
backgroundColor: isSelected
|
|
624
|
-
? theme.
|
|
681
|
+
? theme.hoverBackground
|
|
625
682
|
: theme.surfaceActive,
|
|
626
683
|
},
|
|
627
684
|
},
|
|
@@ -682,6 +739,7 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
682
739
|
onRowContextMenu,
|
|
683
740
|
onColumnResize,
|
|
684
741
|
rowHeight,
|
|
742
|
+
rowInset = ROW_INSET,
|
|
685
743
|
estimatedRowHeight,
|
|
686
744
|
virtual = 'auto',
|
|
687
745
|
overscan = DEFAULT_OVERSCAN,
|
|
@@ -809,6 +867,8 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
809
867
|
const hintShown = useRef(false);
|
|
810
868
|
const userWidthsRef = useRef(userWidths);
|
|
811
869
|
userWidthsRef.current = userWidths;
|
|
870
|
+
const rowInsetRef = useRef(rowInset);
|
|
871
|
+
rowInsetRef.current = rowInset;
|
|
812
872
|
|
|
813
873
|
/** Declared uniform: divide, never measure — core's model. */
|
|
814
874
|
const uniform = rowHeight !== undefined;
|
|
@@ -846,11 +906,29 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
846
906
|
const { first, last, above, below } = win.slice;
|
|
847
907
|
|
|
848
908
|
/** Columns resolve to pixels once, at the table level, per (columns,
|
|
849
|
-
* viewport, resizes) — every row agrees on the grid by construction.
|
|
909
|
+
* viewport, resizes) — every row agrees on the grid by construction.
|
|
910
|
+
* Into the *inset* box: the grid gives up `rowInset` at each edge, so a
|
|
911
|
+
* flex column fills what is left instead of pushing the last few pixels
|
|
912
|
+
* under a horizontal scrollbar that was not there before. */
|
|
913
|
+
const gridWidth = Math.max(0, view.width - rowInset * 2);
|
|
850
914
|
const { widths, total } = useMemo(
|
|
851
|
-
() => resolveWidths(columns, userWidths,
|
|
852
|
-
[columns, userWidths,
|
|
915
|
+
() => resolveWidths(columns, userWidths, gridWidth),
|
|
916
|
+
[columns, userWidths, gridWidth],
|
|
853
917
|
);
|
|
918
|
+
/**
|
|
919
|
+
* The row's corner. `radiusSmall` rather than core's `rowRadius`: that one
|
|
920
|
+
* derives a row's radius from `radiusPopup` less the sheet's border and
|
|
921
|
+
* padding, so the pill and the sheet under it share a centre — and a table
|
|
922
|
+
* owns no sheet. It fills a pane whose radius it cannot know, so there is
|
|
923
|
+
* no outer curve to be concentric with, and `radiusPopup` ("a floating
|
|
924
|
+
* surface … half the text size") is describing a menu laid over the window
|
|
925
|
+
* rather than content in it. Of the two in-window tokens the row takes the
|
|
926
|
+
* tighter: `radius` is the control scale — a button, an input, a card cut
|
|
927
|
+
* into the surface — and this is a mark *on* the surface, transient and
|
|
928
|
+
* borderless. Zero when there is no inset, because a pill has to be inset
|
|
929
|
+
* to be seen as one; rounded and full-bleed just notches the four corners.
|
|
930
|
+
*/
|
|
931
|
+
const rowRadius = rowInset > 0 ? theme.radiusSmall : 0;
|
|
854
932
|
|
|
855
933
|
/**
|
|
856
934
|
* The scroll the table owes a row, and the pane's real offset read back
|
|
@@ -907,7 +985,10 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
907
985
|
const expected = resolveWidths(
|
|
908
986
|
columnsRef.current,
|
|
909
987
|
userWidthsRef.current,
|
|
910
|
-
|
|
988
|
+
// the same inset box the render resolved into, or every row is
|
|
989
|
+
// measured against a grid the table does not have and no height is
|
|
990
|
+
// ever recorded
|
|
991
|
+
Math.max(0, viewRef.current.width - rowInsetRef.current * 2),
|
|
911
992
|
).total;
|
|
912
993
|
const box = body.current;
|
|
913
994
|
const rows = orderedRef.current;
|
|
@@ -1306,6 +1387,9 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
1306
1387
|
{ height: heights.heightAt(entry.index) },
|
|
1307
1388
|
{
|
|
1308
1389
|
backgroundColor: isSelected ? theme.hoverBackground : 'transparent',
|
|
1390
|
+
// Same pill as a real row's, so a placeholder that is replaced
|
|
1391
|
+
// mid-scroll does not change shape as it arrives.
|
|
1392
|
+
borderRadius: rowRadius,
|
|
1309
1393
|
},
|
|
1310
1394
|
typeof rowStyleProp === 'function'
|
|
1311
1395
|
? rowStyleProp(state)
|
|
@@ -1483,6 +1567,7 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
1483
1567
|
rowHeight,
|
|
1484
1568
|
estimate,
|
|
1485
1569
|
theme,
|
|
1570
|
+
radius: rowRadius,
|
|
1486
1571
|
rowStyle: rowStyleProp,
|
|
1487
1572
|
cellStyle: cellStyleProp,
|
|
1488
1573
|
renderRow,
|
|
@@ -1649,7 +1734,17 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
1649
1734
|
},
|
|
1650
1735
|
hx(
|
|
1651
1736
|
'box',
|
|
1652
|
-
{
|
|
1737
|
+
{
|
|
1738
|
+
// `rowInset` first, then the scroll: the header and the rows are
|
|
1739
|
+
// one grid, so the inset that moves the body has to move the
|
|
1740
|
+
// header by the same amount or every caption slides out from over
|
|
1741
|
+
// its column. The strip's own background stays full-bleed — it is
|
|
1742
|
+
// a band across the table, which is exactly what a row is not.
|
|
1743
|
+
style: [
|
|
1744
|
+
s.headerRow,
|
|
1745
|
+
{ marginStart: rowInset - scrollX, width: total },
|
|
1746
|
+
],
|
|
1747
|
+
},
|
|
1653
1748
|
headerCells,
|
|
1654
1749
|
),
|
|
1655
1750
|
),
|
|
@@ -1657,7 +1752,16 @@ export function Table<Row = any>(props: TableProps<Row>): ReactElement {
|
|
|
1657
1752
|
'box',
|
|
1658
1753
|
{
|
|
1659
1754
|
ref: body,
|
|
1660
|
-
|
|
1755
|
+
// The body half of the grid's inset — on the pane rather than on
|
|
1756
|
+
// each row, for three reasons. A row still lays out at exactly
|
|
1757
|
+
// `total`, which is the width `measureRows` insists on before it
|
|
1758
|
+
// will record a height. The spacers a virtualized table stands on
|
|
1759
|
+
// are inset with it, for free. And padding is inside the scrollable
|
|
1760
|
+
// area at both ends, so the trailing inset survives a table scrolled
|
|
1761
|
+
// to the end of columns wider than its pane — a trailing *margin* on
|
|
1762
|
+
// the rows box is dropped from the scroll extent there, and the last
|
|
1763
|
+
// column ends up flush against the edge it was meant to clear.
|
|
1764
|
+
style: [s.body, { paddingStart: rowInset, paddingEnd: rowInset }],
|
|
1661
1765
|
onScroll: (ev) => {
|
|
1662
1766
|
// A scroll this component did not ask for is the user taking over,
|
|
1663
1767
|
// and an owed `scrollToRow` must not yank the list back out from
|
package/src/tree/index.ts
CHANGED
|
@@ -127,6 +127,22 @@ const TWISTY = 12;
|
|
|
127
127
|
* is half of that, so `size` for one reads as its width. */
|
|
128
128
|
const TWISTY_GLYPH = 10;
|
|
129
129
|
const ROW_HEIGHT = 22;
|
|
130
|
+
/**
|
|
131
|
+
* How far a row's wash sits inside the tree's own edge.
|
|
132
|
+
*
|
|
133
|
+
* It is what makes a selection read as a **pill on** the list rather than a
|
|
134
|
+
* band across it. With no inset the wash runs into whatever the tree is
|
|
135
|
+
* mounted against — in a sidebar that is the pane's hairline — and the
|
|
136
|
+
* selected row reads as a stripe cut across the pane instead of a mark on a
|
|
137
|
+
* row. Core's `Menu` insets its rows from the sheet for exactly this reason,
|
|
138
|
+
* and `MENU_PAD` is this number.
|
|
139
|
+
*
|
|
140
|
+
* Horizontal only. Rows stack flush against each other: in a menu it is the
|
|
141
|
+
* sheet's own padding that clears the first and the last, and here it is
|
|
142
|
+
* whatever the app put the tree in. A vertical margin would not reshape the
|
|
143
|
+
* wash, it would spread the list out.
|
|
144
|
+
*/
|
|
145
|
+
const ROW_INSET = 4;
|
|
130
146
|
/**
|
|
131
147
|
* Where `virtual="auto"` starts virtualizing.
|
|
132
148
|
*
|
|
@@ -144,6 +160,13 @@ const s = createStyles({
|
|
|
144
160
|
flexDirection: 'row',
|
|
145
161
|
alignItems: 'center',
|
|
146
162
|
gap: 4,
|
|
163
|
+
// The wash's inset — see `ROW_INSET`. It lives here rather than beside
|
|
164
|
+
// the colours so that the skeleton row wears the same shape, and so that
|
|
165
|
+
// an app can take it back off: `styles.row` merges last, and
|
|
166
|
+
// `{ marginStart: 0, marginEnd: 0, borderRadius: 0 }` is the full-bleed
|
|
167
|
+
// band this used to be.
|
|
168
|
+
marginStart: ROW_INSET,
|
|
169
|
+
marginEnd: ROW_INSET,
|
|
147
170
|
paddingEnd: 8,
|
|
148
171
|
paddingTop: 3,
|
|
149
172
|
paddingBottom: 3,
|
|
@@ -667,10 +690,45 @@ function TreeRowView<T>(props: TreeRowViewProps<T>): ReactElement {
|
|
|
667
690
|
// index reads back what it actually became.
|
|
668
691
|
{ minHeight: rowHeight },
|
|
669
692
|
// The indent is what says "inside", so it is measured from the edge
|
|
670
|
-
// the row's label begins at
|
|
693
|
+
// the row's label begins at — which is the *wash's* edge now, not
|
|
694
|
+
// the tree's, and `ROW_INSET` is deliberately not subtracted back
|
|
695
|
+
// out here. Both readings move something: subtract it and the label
|
|
696
|
+
// stays where it was but ends up flush against the pill it sits in,
|
|
697
|
+
// which is what a pill with no padding looks like; leave it and the
|
|
698
|
+
// whole tree steps over by four pixels once, which nothing inside it
|
|
699
|
+
// can tell apart from a container four pixels narrower. So the
|
|
700
|
+
// padding is the pill's own clearance and the tree takes the shift.
|
|
701
|
+
// The guides are measured from the same edge and move with it, so a
|
|
702
|
+
// branch edge still meets the start of the row it belongs to.
|
|
671
703
|
{ paddingStart: renderGuide ? 4 : 4 + row.depth * indent },
|
|
672
704
|
{
|
|
673
705
|
backgroundColor: isSelected ? theme.hoverBackground : 'transparent',
|
|
706
|
+
// Rounded on the *window's* scale, not a popup's.
|
|
707
|
+
//
|
|
708
|
+
// `rowRadius` — what core's `Menu` and `Select` use — derives a
|
|
709
|
+
// row's radius from `radiusPopup`, less the sheet's border and
|
|
710
|
+
// padding, so that the pill's corner and the sheet's share a
|
|
711
|
+
// centre. That derivation needs an outer curve to be concentric
|
|
712
|
+
// with, and a tree has none: it fills whatever the app mounted it
|
|
713
|
+
// in — a sidebar, a split pane, a dialog — and cannot know that
|
|
714
|
+
// container's radius, or whether it has one. `radiusPopup` is the
|
|
715
|
+
// wrong parent by its own definition anyway ("a floating surface …
|
|
716
|
+
// half the text size"): a tree is content in the window, not a
|
|
717
|
+
// sheet laid over it.
|
|
718
|
+
//
|
|
719
|
+
// That leaves the two in-window tokens, and the row takes the
|
|
720
|
+
// tighter of them. `radius` is the control scale — a button, an
|
|
721
|
+
// input, a card cut into the surface — and this is not a control
|
|
722
|
+
// but a mark *on* the surface: transient, borderless, following
|
|
723
|
+
// the pointer. `radiusSmall` is that step down — the same relation
|
|
724
|
+
// `radiusPopupItem` has to `radiusPopup`, one scale in.
|
|
725
|
+
//
|
|
726
|
+
// An app that does own the sheet can still have the concentric
|
|
727
|
+
// version, because it is the one that knows the radius to be
|
|
728
|
+
// concentric with — `styles={{ row: { borderRadius:
|
|
729
|
+
// rowRadius(theme, border, inset) } }}`, with the inset it also
|
|
730
|
+
// sets here.
|
|
731
|
+
borderRadius: theme.radiusSmall,
|
|
674
732
|
// The row's ink, said once: `color` inherits, so the label takes
|
|
675
733
|
// it without being handed it.
|
|
676
734
|
color,
|
|
@@ -684,9 +742,23 @@ function TreeRowView<T>(props: TreeRowViewProps<T>): ReactElement {
|
|
|
684
742
|
// The selection only moves on the release, and `:active` marks
|
|
685
743
|
// the whole press chain, so a press on the label or the twisty
|
|
686
744
|
// still darkens the row it is in.
|
|
745
|
+
//
|
|
746
|
+
// The pressed colour comes from the ramp the row is already
|
|
747
|
+
// painted with. An unselected row is on the surface ramp, so it is
|
|
748
|
+
// `surfaceActive`. A selected row is washed with `hoverBackground`,
|
|
749
|
+
// and `accentActive` — what this used to say — is the pressed step
|
|
750
|
+
// of `accent`: a different token that merely *holds* the same
|
|
751
|
+
// colour in both stock palettes. Move the accent and the press
|
|
752
|
+
// flashes something the tree never wears at rest; a yellow accent
|
|
753
|
+
// over a blue selection gives a yellow press, and the row's ink is
|
|
754
|
+
// still `hoverText`, picked to be legible on the blue. There is no
|
|
755
|
+
// darker step of `hoverBackground` in the palette to reach for and
|
|
756
|
+
// the selected row is already the strongest fill in the list, so
|
|
757
|
+
// it keeps its wash: the click is answered by what it does, the
|
|
758
|
+
// selection or the activation on the second one.
|
|
687
759
|
':active': {
|
|
688
760
|
backgroundColor: isSelected
|
|
689
|
-
? theme.
|
|
761
|
+
? theme.hoverBackground
|
|
690
762
|
: theme.surfaceActive,
|
|
691
763
|
},
|
|
692
764
|
},
|
|
@@ -1319,6 +1391,9 @@ export function Tree<T = TreeItem>({
|
|
|
1319
1391
|
{ height: index.heightAt(row.index) },
|
|
1320
1392
|
{
|
|
1321
1393
|
backgroundColor: isSelected ? theme.hoverBackground : 'transparent',
|
|
1394
|
+
// Same pill as a real row's, so a placeholder that is replaced
|
|
1395
|
+
// mid-scroll does not change shape as it arrives.
|
|
1396
|
+
borderRadius: theme.radiusSmall,
|
|
1322
1397
|
},
|
|
1323
1398
|
typeof rowStyleProp === 'function'
|
|
1324
1399
|
? rowStyleProp(state)
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import type { MessageBus } from 'react-x11';
|
|
2
|
-
/** One calendar the desktop knows about. */
|
|
3
|
-
export interface DesktopCalendarInfo {
|
|
4
|
-
uid: string;
|
|
5
|
-
/** The name shown in the desktop's own calendar UI. */
|
|
6
|
-
name: string;
|
|
7
|
-
enabled: boolean;
|
|
8
|
-
/** The colour that UI draws it in — worth carrying into a day marker. */
|
|
9
|
-
color?: string;
|
|
10
|
-
/** `caldav`, `google`, `local`, `webcal`… */
|
|
11
|
-
backend?: string;
|
|
12
|
-
readOnly: boolean;
|
|
13
|
-
/** Set when the calendar came from an Online Accounts login. */
|
|
14
|
-
account?: string;
|
|
15
|
-
}
|
|
16
|
-
/** One occurrence, already expanded out of any recurrence rule. */
|
|
17
|
-
export interface DesktopEvent {
|
|
18
|
-
uid: string;
|
|
19
|
-
summary: string;
|
|
20
|
-
location?: string;
|
|
21
|
-
description?: string;
|
|
22
|
-
start: Date;
|
|
23
|
-
end: Date;
|
|
24
|
-
allDay: boolean;
|
|
25
|
-
recurring: boolean;
|
|
26
|
-
calendar: {
|
|
27
|
-
uid: string;
|
|
28
|
-
name: string;
|
|
29
|
-
color?: string;
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
/** A calendar that would not answer. One broken backend is not a failure. */
|
|
33
|
-
export interface DesktopCalendarError {
|
|
34
|
-
calendar: DesktopCalendarInfo;
|
|
35
|
-
message: string;
|
|
36
|
-
}
|
|
37
|
-
export interface EventsResult {
|
|
38
|
-
events: DesktopEvent[];
|
|
39
|
-
errors: DesktopCalendarError[];
|
|
40
|
-
}
|
|
41
|
-
/** What `watch` reports. Deliberately thin: re-query rather than patch. */
|
|
42
|
-
export interface CalendarChange {
|
|
43
|
-
calendar: DesktopCalendarInfo;
|
|
44
|
-
kind: 'ObjectsAdded' | 'ObjectsModified' | 'ObjectsRemoved';
|
|
45
|
-
count: number;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* A source's whole configuration is an ini-style keyfile carried in one D-Bus
|
|
49
|
-
* property, so it has to be parsed to find out whether a source is even a
|
|
50
|
-
* calendar (as opposed to an address book, a mail account or a task list).
|
|
51
|
-
*/
|
|
52
|
-
export declare function parseKeyFile(text: string): Record<string, Record<string, string>>;
|
|
53
|
-
/**
|
|
54
|
-
* The desktop's calendars, read over a bus someone else owns.
|
|
55
|
-
*
|
|
56
|
-
* ```ts
|
|
57
|
-
* const ref = await sessionBus();
|
|
58
|
-
* if (!ref) return; // no bus here; no calendars
|
|
59
|
-
* const desktop = new DesktopCalendar(ref.bus);
|
|
60
|
-
* const { events } = await desktop.eventsBetween(from, to);
|
|
61
|
-
* ```
|
|
62
|
-
*
|
|
63
|
-
* Nothing here closes the connection, because nothing here opened it. Call
|
|
64
|
-
* `dispose()` to drop the views this instance started, then release your own
|
|
65
|
-
* reference to the bus.
|
|
66
|
-
*/
|
|
67
|
-
export declare class DesktopCalendar {
|
|
68
|
-
#private;
|
|
69
|
-
constructor(bus: MessageBus);
|
|
70
|
-
/** Every calendar the desktop knows about, colour included. */
|
|
71
|
-
listCalendars(): Promise<DesktopCalendarInfo[]>;
|
|
72
|
-
/**
|
|
73
|
-
* Expanded occurrences between two `Date`s, across the calendars given (or
|
|
74
|
-
* every enabled one). Sorted by start.
|
|
75
|
-
*
|
|
76
|
-
* A backend that is offline or broken contributes an entry in `errors`
|
|
77
|
-
* rather than throwing: one unreachable CalDAV server must not blank a
|
|
78
|
-
* whole month of the user's own local calendar.
|
|
79
|
-
*/
|
|
80
|
-
eventsBetween(from: Date, to: Date, options?: {
|
|
81
|
-
calendars?: DesktopCalendarInfo[];
|
|
82
|
-
}): Promise<EventsResult>;
|
|
83
|
-
/**
|
|
84
|
-
* Live updates: `onChange` fires whenever anything in the range moves, so
|
|
85
|
-
* the caller can re-query. Returns an unsubscribe function.
|
|
86
|
-
*
|
|
87
|
-
* Deliberately a "something changed" signal rather than a patch — a
|
|
88
|
-
* recurrence master edited three months away can change what today looks
|
|
89
|
-
* like, and re-running the query is both simpler and correct.
|
|
90
|
-
*
|
|
91
|
-
* **Changes only.** What is in the range already is what `eventsBetween`
|
|
92
|
-
* answered; `onChange` fires for what happens after that. See
|
|
93
|
-
* {@link VIEW_FLAGS_NONE} for the loop that reporting the initial contents
|
|
94
|
-
* as a change costs a caller who re-queries on one.
|
|
95
|
-
*/
|
|
96
|
-
watch(from: Date, to: Date, onChange: (change: CalendarChange) => void, options?: {
|
|
97
|
-
calendars?: DesktopCalendarInfo[];
|
|
98
|
-
}): Promise<() => Promise<void>>;
|
|
99
|
-
/** Stop every view this instance started. Does **not** touch the bus. */
|
|
100
|
-
dispose(): Promise<void>;
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=eds.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eds.d.ts","sourceRoot":"","sources":["../../src/desktop-calendar/eds.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AA2B5C,4CAA4C;AAC5C,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;IACV,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAED,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,2EAA2E;AAC3E,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,IAAI,EAAE,cAAc,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;IAC5D,KAAK,EAAE,MAAM,CAAC;CACf;AAiBD;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAmBxC;AAkBD;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;;IAM1B,YAAY,GAAG,EAAE,UAAU,EAE1B;IAED,+DAA+D;IACzD,aAAa,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA6BpD;IAoDD;;;;;;;OAOG;IACG,aAAa,CACjB,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,IAAI,EACR,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAA;KAAO,GAClD,OAAO,CAAC,YAAY,CAAC,CAoCvB;IAgFD;;;;;;;;;;;;OAYG;IACG,KAAK,CACT,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,IAAI,EACR,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,EAC1C,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAA;KAAO,GAClD,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAgE9B;IAED,yEAAyE;IACnE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAY7B;CACF"}
|