@issuegraph/editor 0.1.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/LICENSE +201 -0
- package/README.md +238 -0
- package/dist/audit/findings.d.ts +225 -0
- package/dist/audit/findings.d.ts.map +1 -0
- package/dist/audit/findings.js +348 -0
- package/dist/audit/findings.js.map +1 -0
- package/dist/audit/styles.d.ts +37 -0
- package/dist/audit/styles.d.ts.map +1 -0
- package/dist/audit/styles.js +72 -0
- package/dist/audit/styles.js.map +1 -0
- package/dist/audit/surface.d.ts +155 -0
- package/dist/audit/surface.d.ts.map +1 -0
- package/dist/audit/surface.js +202 -0
- package/dist/audit/surface.js.map +1 -0
- package/dist/create/draft.d.ts +119 -0
- package/dist/create/draft.d.ts.map +1 -0
- package/dist/create/draft.js +114 -0
- package/dist/create/draft.js.map +1 -0
- package/dist/create/keys.d.ts +225 -0
- package/dist/create/keys.d.ts.map +1 -0
- package/dist/create/keys.js +228 -0
- package/dist/create/keys.js.map +1 -0
- package/dist/create/placement.d.ts +69 -0
- package/dist/create/placement.d.ts.map +1 -0
- package/dist/create/placement.js +76 -0
- package/dist/create/placement.js.map +1 -0
- package/dist/firstpass/batch.d.ts +190 -0
- package/dist/firstpass/batch.d.ts.map +1 -0
- package/dist/firstpass/batch.js +143 -0
- package/dist/firstpass/batch.js.map +1 -0
- package/dist/firstpass/candidates.d.ts +128 -0
- package/dist/firstpass/candidates.d.ts.map +1 -0
- package/dist/firstpass/candidates.js +39 -0
- package/dist/firstpass/candidates.js.map +1 -0
- package/dist/firstpass/keys.d.ts +90 -0
- package/dist/firstpass/keys.d.ts.map +1 -0
- package/dist/firstpass/keys.js +112 -0
- package/dist/firstpass/keys.js.map +1 -0
- package/dist/firstpass/queue.d.ts +183 -0
- package/dist/firstpass/queue.d.ts.map +1 -0
- package/dist/firstpass/queue.js +159 -0
- package/dist/firstpass/queue.js.map +1 -0
- package/dist/firstpass/render.d.ts +100 -0
- package/dist/firstpass/render.d.ts.map +1 -0
- package/dist/firstpass/render.js +216 -0
- package/dist/firstpass/render.js.map +1 -0
- package/dist/firstpass/styles.d.ts +36 -0
- package/dist/firstpass/styles.d.ts.map +1 -0
- package/dist/firstpass/styles.js +148 -0
- package/dist/firstpass/styles.js.map +1 -0
- package/dist/firstpass/view.d.ts +82 -0
- package/dist/firstpass/view.d.ts.map +1 -0
- package/dist/firstpass/view.js +60 -0
- package/dist/firstpass/view.js.map +1 -0
- package/dist/firstpass/words.d.ts +105 -0
- package/dist/firstpass/words.d.ts.map +1 -0
- package/dist/firstpass/words.js +28 -0
- package/dist/firstpass/words.js.map +1 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/overlay/grammar.d.ts +259 -0
- package/dist/overlay/grammar.d.ts.map +1 -0
- package/dist/overlay/grammar.js +223 -0
- package/dist/overlay/grammar.js.map +1 -0
- package/dist/overlay/render.d.ts +125 -0
- package/dist/overlay/render.d.ts.map +1 -0
- package/dist/overlay/render.js +439 -0
- package/dist/overlay/render.js.map +1 -0
- package/dist/overlay/styles.d.ts +41 -0
- package/dist/overlay/styles.d.ts.map +1 -0
- package/dist/overlay/styles.js +124 -0
- package/dist/overlay/styles.js.map +1 -0
- package/dist/picker/render.d.ts +80 -0
- package/dist/picker/render.d.ts.map +1 -0
- package/dist/picker/render.js +112 -0
- package/dist/picker/render.js.map +1 -0
- package/dist/picker/styles.d.ts +26 -0
- package/dist/picker/styles.d.ts.map +1 -0
- package/dist/picker/styles.js +116 -0
- package/dist/picker/styles.js.map +1 -0
- package/dist/picker/view.d.ts +135 -0
- package/dist/picker/view.d.ts.map +1 -0
- package/dist/picker/view.js +117 -0
- package/dist/picker/view.js.map +1 -0
- package/dist/picker/words.d.ts +53 -0
- package/dist/picker/words.d.ts.map +1 -0
- package/dist/picker/words.js +28 -0
- package/dist/picker/words.js.map +1 -0
- package/dist/reevaluate/render.d.ts +77 -0
- package/dist/reevaluate/render.d.ts.map +1 -0
- package/dist/reevaluate/render.js +211 -0
- package/dist/reevaluate/render.js.map +1 -0
- package/dist/reevaluate/styles.d.ts +24 -0
- package/dist/reevaluate/styles.d.ts.map +1 -0
- package/dist/reevaluate/styles.js +182 -0
- package/dist/reevaluate/styles.js.map +1 -0
- package/dist/reevaluate/view.d.ts +102 -0
- package/dist/reevaluate/view.d.ts.map +1 -0
- package/dist/reevaluate/view.js +111 -0
- package/dist/reevaluate/view.js.map +1 -0
- package/dist/reevaluate/words.d.ts +54 -0
- package/dist/reevaluate/words.d.ts.map +1 -0
- package/dist/reevaluate/words.js +29 -0
- package/dist/reevaluate/words.js.map +1 -0
- package/dist/scale/commands.d.ts +60 -0
- package/dist/scale/commands.d.ts.map +1 -0
- package/dist/scale/commands.js +49 -0
- package/dist/scale/commands.js.map +1 -0
- package/dist/scale/ladder.d.ts +141 -0
- package/dist/scale/ladder.d.ts.map +1 -0
- package/dist/scale/ladder.js +243 -0
- package/dist/scale/ladder.js.map +1 -0
- package/dist/scale/render.d.ts +85 -0
- package/dist/scale/render.d.ts.map +1 -0
- package/dist/scale/render.js +194 -0
- package/dist/scale/render.js.map +1 -0
- package/dist/scale/styles.d.ts +21 -0
- package/dist/scale/styles.d.ts.map +1 -0
- package/dist/scale/styles.js +105 -0
- package/dist/scale/styles.js.map +1 -0
- package/dist/workspace/inspector.d.ts +117 -0
- package/dist/workspace/inspector.d.ts.map +1 -0
- package/dist/workspace/inspector.js +140 -0
- package/dist/workspace/inspector.js.map +1 -0
- package/dist/workspace/rail.d.ts +122 -0
- package/dist/workspace/rail.d.ts.map +1 -0
- package/dist/workspace/rail.js +216 -0
- package/dist/workspace/rail.js.map +1 -0
- package/dist/workspace/render.d.ts +139 -0
- package/dist/workspace/render.d.ts.map +1 -0
- package/dist/workspace/render.js +366 -0
- package/dist/workspace/render.js.map +1 -0
- package/dist/workspace/selection.d.ts +92 -0
- package/dist/workspace/selection.d.ts.map +1 -0
- package/dist/workspace/selection.js +83 -0
- package/dist/workspace/selection.js.map +1 -0
- package/dist/workspace/styles.d.ts +39 -0
- package/dist/workspace/styles.d.ts.map +1 -0
- package/dist/workspace/styles.js +313 -0
- package/dist/workspace/styles.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The picker's words. Supplied by the host, never by this package.
|
|
3
|
+
*
|
|
4
|
+
* Same contract, and the same reasoning, as
|
|
5
|
+
* {@link ../reevaluate/words.ts ChangeWords}: the store deliberately stops at
|
|
6
|
+
* data rather than prose, and a default vocabulary here would take that choice
|
|
7
|
+
* back one layer down. It is sharper for this surface than for the summary,
|
|
8
|
+
* because what is being worded is a RELATIONSHIP — "is blocked by" carries a
|
|
9
|
+
* word order as well as a language, and a package that shipped the phrase would
|
|
10
|
+
* ship an English clause its consumers could not translate or reverse.
|
|
11
|
+
*
|
|
12
|
+
* SO IT IS REQUIRED, NOT DEFAULTED, exactly as `StoreConfig.derive` is: a
|
|
13
|
+
* default would be a second implementation of something this layer is not
|
|
14
|
+
* entitled to decide.
|
|
15
|
+
*
|
|
16
|
+
* ## One vocabulary, read in two places
|
|
17
|
+
*
|
|
18
|
+
* {@link PickerWords.kinds} words both a picker OPTION ("is blocked by", chosen
|
|
19
|
+
* from a list of five) and the DIRECTION STATEMENT it produces ("#530 is
|
|
20
|
+
* blocked by #602"). One entry has to read in both positions, which is the same
|
|
21
|
+
* constraint `ChangeWords.facets` carries for the summary and its chips.
|
|
22
|
+
*
|
|
23
|
+
* A host wanting two registers — a short label in the list, a full clause in
|
|
24
|
+
* the statement — renders {@link ../picker/view.ts PickerView} itself. Nothing
|
|
25
|
+
* in the default render is load-bearing for that.
|
|
26
|
+
*/
|
|
27
|
+
import type { EdgeKind } from '@issuegraph/store';
|
|
28
|
+
export interface PickerWords {
|
|
29
|
+
/**
|
|
30
|
+
* One relational phrase per kind.
|
|
31
|
+
*
|
|
32
|
+
* `Record<EdgeKind, string>` rather than a partial map: a kind with no phrase
|
|
33
|
+
* would render as a bare reference pair, which reads as a DIFFERENT
|
|
34
|
+
* relationship rather than as a missing label — and mistaking one
|
|
35
|
+
* relationship for another is the encoding error this surface exists to
|
|
36
|
+
* prevent. A kind added to the format fails a host's build here, which is
|
|
37
|
+
* where it can be fixed.
|
|
38
|
+
*/
|
|
39
|
+
readonly kinds: Readonly<Record<EdgeKind, string>>;
|
|
40
|
+
/** Names the picker for a screen reader and for a visible heading. */
|
|
41
|
+
readonly heading: string;
|
|
42
|
+
/** The control that reverses a directed relationship. */
|
|
43
|
+
readonly flip: string;
|
|
44
|
+
/**
|
|
45
|
+
* Marks the option the edge already carries.
|
|
46
|
+
*
|
|
47
|
+
* A word rather than a colour: "which one is it now" is the question the
|
|
48
|
+
* picker is opened to answer, and a purely visual answer is unavailable to a
|
|
49
|
+
* screen reader and to a host with a monochrome theme.
|
|
50
|
+
*/
|
|
51
|
+
readonly current: string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=words.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"words.d.ts","sourceRoot":"","sources":["../../src/picker/words.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,sEAAsE;IACtE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The picker's words. Supplied by the host, never by this package.
|
|
3
|
+
*
|
|
4
|
+
* Same contract, and the same reasoning, as
|
|
5
|
+
* {@link ../reevaluate/words.ts ChangeWords}: the store deliberately stops at
|
|
6
|
+
* data rather than prose, and a default vocabulary here would take that choice
|
|
7
|
+
* back one layer down. It is sharper for this surface than for the summary,
|
|
8
|
+
* because what is being worded is a RELATIONSHIP — "is blocked by" carries a
|
|
9
|
+
* word order as well as a language, and a package that shipped the phrase would
|
|
10
|
+
* ship an English clause its consumers could not translate or reverse.
|
|
11
|
+
*
|
|
12
|
+
* SO IT IS REQUIRED, NOT DEFAULTED, exactly as `StoreConfig.derive` is: a
|
|
13
|
+
* default would be a second implementation of something this layer is not
|
|
14
|
+
* entitled to decide.
|
|
15
|
+
*
|
|
16
|
+
* ## One vocabulary, read in two places
|
|
17
|
+
*
|
|
18
|
+
* {@link PickerWords.kinds} words both a picker OPTION ("is blocked by", chosen
|
|
19
|
+
* from a list of five) and the DIRECTION STATEMENT it produces ("#530 is
|
|
20
|
+
* blocked by #602"). One entry has to read in both positions, which is the same
|
|
21
|
+
* constraint `ChangeWords.facets` carries for the summary and its chips.
|
|
22
|
+
*
|
|
23
|
+
* A host wanting two registers — a short label in the list, a full clause in
|
|
24
|
+
* the statement — renders {@link ../picker/view.ts PickerView} itself. Nothing
|
|
25
|
+
* in the default render is load-bearing for that.
|
|
26
|
+
*/
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=words.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"words.js","sourceRoot":"","sources":["../../src/picker/words.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The re-evaluate surface, as markup: the rail, a summary of what the last edit
|
|
3
|
+
* did to it, and a delta chip for each row that changed.
|
|
4
|
+
*
|
|
5
|
+
* ## It draws nothing inside a row
|
|
6
|
+
*
|
|
7
|
+
* The rail is `@issuegraph/viewer`'s linear projection, composed here as a SPEC
|
|
8
|
+
* rather than as a string — `renderViewer` hands back `scene.root`, so the
|
|
9
|
+
* viewer's tree nests inside this one and every byte still comes out of
|
|
10
|
+
* `renderMarkup`. Nothing is concatenated by hand, and no attribute value in
|
|
11
|
+
* this package is ever escaped by anything but the one renderer.
|
|
12
|
+
*
|
|
13
|
+
* That is what makes the design's rule structural instead of asserted:
|
|
14
|
+
* **unaffected rows are left completely alone** because this package never
|
|
15
|
+
* touches a row. The rejected alternative — splice chips into the rail's markup
|
|
16
|
+
* string — would have re-introduced exactly the hand-built escaping surface the
|
|
17
|
+
* spec grammar exists to remove.
|
|
18
|
+
*
|
|
19
|
+
* ## The chips are a KEYED LIST, and this package does not position them
|
|
20
|
+
*
|
|
21
|
+
* Said plainly because the earlier wording did not: `data-ig-key` has no
|
|
22
|
+
* browser behaviour of its own. The chips render as a list beside the rail, and
|
|
23
|
+
* putting one ON its row needs that row's geometry — which only a mount has,
|
|
24
|
+
* and this package has no mount. Naming it an overlay while shipping a
|
|
25
|
+
* normal-flow list claimed a positioning this markup cannot do.
|
|
26
|
+
*
|
|
27
|
+
* So the list is built to stand on its own instead: every chip NAMES the row it
|
|
28
|
+
* describes, which is what lets a reader account for the rows that got no chip.
|
|
29
|
+
* The key is published for the mount that will position them, and that mount
|
|
30
|
+
* lands with the change that assembles the workspace — the same boundary the
|
|
31
|
+
* scale ladder already draws when it defers listener wiring and focus
|
|
32
|
+
* restoration to whoever owns the mount.
|
|
33
|
+
*
|
|
34
|
+
* ## Two rejected alternatives from the design, recorded so they stay rejected
|
|
35
|
+
*
|
|
36
|
+
* A before/after side-by-side makes the owner redo the comparison the machine
|
|
37
|
+
* already did, and doubles the surface at 300 rows. An animated re-sort is
|
|
38
|
+
* pretty once and unusable in a loop, because rows moving under the cursor mean
|
|
39
|
+
* the next edit targets the wrong thing. Neither is reachable from here.
|
|
40
|
+
*
|
|
41
|
+
* ## Nothing dismisses itself
|
|
42
|
+
*
|
|
43
|
+
* There is no timer, and there is no view state. `Store.dismissChange()` is
|
|
44
|
+
* already the only thing besides the next edit that clears the summary, so this
|
|
45
|
+
* renders a control publishing `data-ig-command="dismiss-change"` and lets the
|
|
46
|
+
* store stay the single source of truth. A second copy of "has this been
|
|
47
|
+
* dismissed" held out here is the drift the command grammar exists to avoid.
|
|
48
|
+
*/
|
|
49
|
+
import { type Theme, type ViewerDocument } from '@issuegraph/viewer';
|
|
50
|
+
import type { OrderChange, OrderStatus } from '@issuegraph/store';
|
|
51
|
+
import type { ChangeWords } from './words.ts';
|
|
52
|
+
import { type ReevaluateView } from './view.ts';
|
|
53
|
+
export interface ReevaluateOptions {
|
|
54
|
+
/**
|
|
55
|
+
* The words. Required — see {@link ChangeWords} for why this package will not
|
|
56
|
+
* invent them.
|
|
57
|
+
*/
|
|
58
|
+
readonly words: ChangeWords;
|
|
59
|
+
/** The store's `lastChange`. Absent means no edit has landed to report. */
|
|
60
|
+
readonly change?: OrderChange | null | undefined;
|
|
61
|
+
/** The store's `order.status`. `held` greys and labels the rail. */
|
|
62
|
+
readonly status?: OrderStatus | undefined;
|
|
63
|
+
readonly theme?: Theme | undefined;
|
|
64
|
+
/** The selector the theme's custom properties are written onto. */
|
|
65
|
+
readonly themeSelector?: string | undefined;
|
|
66
|
+
}
|
|
67
|
+
export interface ReevaluateResult {
|
|
68
|
+
readonly view: ReevaluateView;
|
|
69
|
+
/** The whole surface: the summary, the chips, and the rail inside one root. */
|
|
70
|
+
readonly markup: string;
|
|
71
|
+
/** The viewer's stylesheet, the theme, and this surface's own. Install all. */
|
|
72
|
+
readonly styles: string;
|
|
73
|
+
readonly diagnostics: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
/** Render the order, and what the last edit did to it. */
|
|
76
|
+
export declare function renderReevaluate(input: ViewerDocument, options: ReevaluateOptions): ReevaluateResult;
|
|
77
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/reevaluate/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,cAAc,EAMpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAa,MAAM,mBAAmB,CAAC;AAE7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAuC,KAAK,cAAc,EAAkB,MAAM,WAAW,CAAC;AAGrG,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAqJD,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,iBAAiB,GACzB,gBAAgB,CA8ClB"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The re-evaluate surface, as markup: the rail, a summary of what the last edit
|
|
3
|
+
* did to it, and a delta chip for each row that changed.
|
|
4
|
+
*
|
|
5
|
+
* ## It draws nothing inside a row
|
|
6
|
+
*
|
|
7
|
+
* The rail is `@issuegraph/viewer`'s linear projection, composed here as a SPEC
|
|
8
|
+
* rather than as a string — `renderViewer` hands back `scene.root`, so the
|
|
9
|
+
* viewer's tree nests inside this one and every byte still comes out of
|
|
10
|
+
* `renderMarkup`. Nothing is concatenated by hand, and no attribute value in
|
|
11
|
+
* this package is ever escaped by anything but the one renderer.
|
|
12
|
+
*
|
|
13
|
+
* That is what makes the design's rule structural instead of asserted:
|
|
14
|
+
* **unaffected rows are left completely alone** because this package never
|
|
15
|
+
* touches a row. The rejected alternative — splice chips into the rail's markup
|
|
16
|
+
* string — would have re-introduced exactly the hand-built escaping surface the
|
|
17
|
+
* spec grammar exists to remove.
|
|
18
|
+
*
|
|
19
|
+
* ## The chips are a KEYED LIST, and this package does not position them
|
|
20
|
+
*
|
|
21
|
+
* Said plainly because the earlier wording did not: `data-ig-key` has no
|
|
22
|
+
* browser behaviour of its own. The chips render as a list beside the rail, and
|
|
23
|
+
* putting one ON its row needs that row's geometry — which only a mount has,
|
|
24
|
+
* and this package has no mount. Naming it an overlay while shipping a
|
|
25
|
+
* normal-flow list claimed a positioning this markup cannot do.
|
|
26
|
+
*
|
|
27
|
+
* So the list is built to stand on its own instead: every chip NAMES the row it
|
|
28
|
+
* describes, which is what lets a reader account for the rows that got no chip.
|
|
29
|
+
* The key is published for the mount that will position them, and that mount
|
|
30
|
+
* lands with the change that assembles the workspace — the same boundary the
|
|
31
|
+
* scale ladder already draws when it defers listener wiring and focus
|
|
32
|
+
* restoration to whoever owns the mount.
|
|
33
|
+
*
|
|
34
|
+
* ## Two rejected alternatives from the design, recorded so they stay rejected
|
|
35
|
+
*
|
|
36
|
+
* A before/after side-by-side makes the owner redo the comparison the machine
|
|
37
|
+
* already did, and doubles the surface at 300 rows. An animated re-sort is
|
|
38
|
+
* pretty once and unusable in a loop, because rows moving under the cursor mean
|
|
39
|
+
* the next edit targets the wrong thing. Neither is reachable from here.
|
|
40
|
+
*
|
|
41
|
+
* ## Nothing dismisses itself
|
|
42
|
+
*
|
|
43
|
+
* There is no timer, and there is no view state. `Store.dismissChange()` is
|
|
44
|
+
* already the only thing besides the next edit that clears the summary, so this
|
|
45
|
+
* renders a control publishing `data-ig-command="dismiss-change"` and lets the
|
|
46
|
+
* store stay the single source of truth. A second copy of "has this been
|
|
47
|
+
* dismissed" held out here is the drift the command grammar exists to avoid.
|
|
48
|
+
*/
|
|
49
|
+
import { KEY_ATTRIBUTE, element, renderMarkup, renderViewer, resolveTheme, } from '@issuegraph/viewer';
|
|
50
|
+
import { reevaluateView } from "./view.js";
|
|
51
|
+
import { reevaluateStylesheet } from "./styles.js";
|
|
52
|
+
function countWord(count, word) {
|
|
53
|
+
return [
|
|
54
|
+
element('span', { class: 'ig-change-count' }, [String(count)]),
|
|
55
|
+
element('span', { class: 'ig-change-word' }, [word]),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
function summarySpec(summary, words) {
|
|
59
|
+
return element('div', {
|
|
60
|
+
class: 'ig-change-summary',
|
|
61
|
+
// Omitted rather than falsified while there is nothing to report: an
|
|
62
|
+
// element() attribute whose value is `undefined` is not written at all,
|
|
63
|
+
// and `data-unchanged="false"` would claim an edit landed and moved
|
|
64
|
+
// nothing when no edit has landed.
|
|
65
|
+
'data-unchanged': summary === null ? undefined : summary.unchanged ? 'true' : 'false',
|
|
66
|
+
'data-op': summary?.op,
|
|
67
|
+
'data-mutation': summary?.mutationId,
|
|
68
|
+
}, [
|
|
69
|
+
// THE LIVE REGION IS ALWAYS MOUNTED, AND EMPTY UNTIL THERE IS SOMETHING
|
|
70
|
+
// TO SAY. A `role="status"` node that is CREATED already carrying its
|
|
71
|
+
// text is not reliably announced — the region has to exist first and
|
|
72
|
+
// then have its contents change — so rendering it only alongside a
|
|
73
|
+
// summary would silently lose the FIRST summary after a load, which is
|
|
74
|
+
// the one a reader is most likely to be waiting for.
|
|
75
|
+
//
|
|
76
|
+
// It is also why the region is this wrapper rather than the content
|
|
77
|
+
// inside it: an edit that moved something renders a list and one that
|
|
78
|
+
// moved nothing renders a paragraph, so a role on either would come and
|
|
79
|
+
// go with the shape. And the dismiss button stays OUTSIDE, or its label
|
|
80
|
+
// would be re-announced with every summary.
|
|
81
|
+
//
|
|
82
|
+
// It is a role, not a timer. Nothing about it expires and the region
|
|
83
|
+
// stays put until the next edit or an explicit dismissal.
|
|
84
|
+
element('div', { class: 'ig-change-line', role: 'status' }, summary === null
|
|
85
|
+
? []
|
|
86
|
+
: [
|
|
87
|
+
// THE ZERO CASE RENDERS, in the summary's own place. An edit that
|
|
88
|
+
// landed and moved nothing is the finding an owner auditing an
|
|
89
|
+
// encoding most needs, and drawing nothing for it is the defect
|
|
90
|
+
// this branch prevents.
|
|
91
|
+
summary.unchanged
|
|
92
|
+
? element('p', { class: 'ig-change-unchanged' }, [words.unchanged])
|
|
93
|
+
: element('ul', { class: 'ig-change-parts' }, summary.parts.map((part) => element('li', { class: 'ig-change-part', 'data-facet': part.facet }, [
|
|
94
|
+
...countWord(part.count, words.facets[part.facet]),
|
|
95
|
+
]))),
|
|
96
|
+
]),
|
|
97
|
+
// ITS OWN CLASS, not the ladder's `.ig-chip`. That class is defined only
|
|
98
|
+
// in `scale/styles.ts`, so borrowing it would leave this control unstyled
|
|
99
|
+
// for a host that installs this surface and not that one. Folding the two
|
|
100
|
+
// chip looks into one rule is the assembling change's call, not this
|
|
101
|
+
// leaf's — it is the change that first has both on screen at once.
|
|
102
|
+
//
|
|
103
|
+
// Absent with no summary: a control that clears nothing is a control that
|
|
104
|
+
// does nothing, and the region above is what has to persist, not this.
|
|
105
|
+
summary === null
|
|
106
|
+
? null
|
|
107
|
+
: element('button', { type: 'button', class: 'ig-change-dismiss', 'data-ig-command': 'dismiss-change' }, [words.dismiss]),
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* What one issue's delta says, as spans.
|
|
112
|
+
*
|
|
113
|
+
* IT NAMES A DIRECTION AND A DISTANCE, NEVER A RANK. `RankMovement.from` and
|
|
114
|
+
* `.to` are the deriver's 0-BASED positions, while the rail beside them renders
|
|
115
|
+
* the viewer's 1-BASED ranks — so printing either as a number would put two
|
|
116
|
+
* different bases side by side and read as an off-by-one. `by` is a distance,
|
|
117
|
+
* which is basis-independent and safe to print. A host that knows the basis and
|
|
118
|
+
* wants the endpoints reads them off `view.chips[].deltas`, which carries every
|
|
119
|
+
* `RankDelta` untouched.
|
|
120
|
+
*/
|
|
121
|
+
function memberSpec(delta, words, named) {
|
|
122
|
+
return element('span', { class: 'ig-delta-member', 'data-ref': delta.ref }, [
|
|
123
|
+
// NAMED ONLY WHEN THE NAME ADDS SOMETHING. On a chip whose single member IS
|
|
124
|
+
// the row, the row key above has already said it and repeating it is noise.
|
|
125
|
+
// Everywhere else the ref is load-bearing: two members reading
|
|
126
|
+
// `lead 1 down 1 down` says the row moved twice rather than that a unit of
|
|
127
|
+
// two each moved down one, and a lone member that is NOT the lead is a
|
|
128
|
+
// change to an issue the row key does not name at all.
|
|
129
|
+
named ? element('span', { class: 'ig-delta-ref' }, [delta.ref]) : null,
|
|
130
|
+
delta.movement === undefined
|
|
131
|
+
? null
|
|
132
|
+
: element('span', {
|
|
133
|
+
class: 'ig-delta-move',
|
|
134
|
+
'data-direction': delta.movement.direction,
|
|
135
|
+
'data-by': delta.movement.by,
|
|
136
|
+
}, [...countWord(delta.movement.by, words.direction[delta.movement.direction])]),
|
|
137
|
+
delta.readiness === undefined
|
|
138
|
+
? null
|
|
139
|
+
: element('span', { class: 'ig-delta-readiness', 'data-readiness': delta.readiness }, [
|
|
140
|
+
words.facets[delta.readiness],
|
|
141
|
+
]),
|
|
142
|
+
delta.presence === undefined
|
|
143
|
+
? null
|
|
144
|
+
: element('span', { class: 'ig-delta-presence', 'data-presence': delta.presence }, [
|
|
145
|
+
words.facets[delta.presence],
|
|
146
|
+
]),
|
|
147
|
+
]);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* One ROW's chip — which can speak for more than one issue.
|
|
151
|
+
*
|
|
152
|
+
* A `together-with` unit is one row and several refs, so its members are nested
|
|
153
|
+
* inside a single chip rather than given one each. Each keeps its own
|
|
154
|
+
* `data-ref`, so a host can still tell which member moved.
|
|
155
|
+
*
|
|
156
|
+
* IT NAMES ITS ROW IN TEXT, not only in `KEY_ATTRIBUTE`. Unpositioned, a chip
|
|
157
|
+
* that carried its key only as an attribute said nothing a reader could see
|
|
158
|
+
* about WHICH row moved — and the rows that did not move are accounted for
|
|
159
|
+
* precisely by not being named here. The key is data, not language, so naming
|
|
160
|
+
* it costs the host no word.
|
|
161
|
+
*/
|
|
162
|
+
function chipSpec(chip, words) {
|
|
163
|
+
// One member whose ref IS the row: the key names it, so naming it again would
|
|
164
|
+
// be the only text on the chip that says nothing. Any other shape — several
|
|
165
|
+
// members, or a lone member the row is not named after — needs each fact
|
|
166
|
+
// attributed, or the chip reads as one row's facts repeated.
|
|
167
|
+
const named = chip.deltas.length > 1 || chip.deltas[0]?.ref !== chip.key;
|
|
168
|
+
return element('li', { class: 'ig-delta-chip', [KEY_ATTRIBUTE]: chip.key }, [
|
|
169
|
+
element('span', { class: 'ig-delta-key' }, [chip.key]),
|
|
170
|
+
...chip.deltas.map((delta) => memberSpec(delta, words, named)),
|
|
171
|
+
]);
|
|
172
|
+
}
|
|
173
|
+
/** Render the order, and what the last edit did to it. */
|
|
174
|
+
export function renderReevaluate(input, options) {
|
|
175
|
+
const status = options.status ?? 'settled';
|
|
176
|
+
const theme = resolveTheme(options.theme);
|
|
177
|
+
const rail = renderViewer(input, {
|
|
178
|
+
projection: 'linear',
|
|
179
|
+
theme,
|
|
180
|
+
...(options.themeSelector === undefined ? {} : { themeSelector: options.themeSelector }),
|
|
181
|
+
});
|
|
182
|
+
const view = reevaluateView(options.change, rail.scene, status);
|
|
183
|
+
const root = element('section', {
|
|
184
|
+
class: 'ig-reevaluate',
|
|
185
|
+
// The rail's own state, on the surface that owns the label for it. The
|
|
186
|
+
// viewer draws the order it was handed; whether that order is the current
|
|
187
|
+
// one is a fact only the store knows.
|
|
188
|
+
'data-order': status,
|
|
189
|
+
}, [
|
|
190
|
+
// "Write landed, order computing" shows the PREVIOUS order, held still,
|
|
191
|
+
// greyed one step and EXPLICITLY LABELLED. A stale-but-labelled order
|
|
192
|
+
// beats a half-computed one, and the rail never shows a rank it is not
|
|
193
|
+
// sure of — which is why nothing here re-ranks anything: the ranks drawn
|
|
194
|
+
// are the ones the caller vouched for, and a chip's movement is drawn as
|
|
195
|
+
// a chip rather than as a rank.
|
|
196
|
+
view.held ? element('p', { class: 'ig-order-computing' }, [options.words.computing]) : null,
|
|
197
|
+
summarySpec(view.summary, options.words),
|
|
198
|
+
view.chips.length === 0
|
|
199
|
+
? null
|
|
200
|
+
: element('ul', { class: 'ig-delta-list' }, view.chips.map((chip) => chipSpec(chip, options.words))),
|
|
201
|
+
// The viewer's own tree, nested rather than concatenated.
|
|
202
|
+
rail.scene.root,
|
|
203
|
+
]);
|
|
204
|
+
return {
|
|
205
|
+
view,
|
|
206
|
+
markup: renderMarkup(root),
|
|
207
|
+
styles: `${rail.styles}\n${reevaluateStylesheet}`,
|
|
208
|
+
diagnostics: [...view.diagnostics, ...rail.diagnostics],
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/reevaluate/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The re-evaluate surface's structural stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* Same contract as the viewer's and the ladder's: layout, weight and state,
|
|
5
|
+
* never a value. Every colour, length and font is a `var(--ig-…)` the host's
|
|
6
|
+
* theme resolves, so a second theme keeps working here too, and
|
|
7
|
+
* `styles.test.ts` scans these bytes for a literal or an unresolvable token.
|
|
8
|
+
*
|
|
9
|
+
* IT ADDS SELECTORS RATHER THAN REDEFINING THEM, with one deliberate exception
|
|
10
|
+
* that is worth naming: the greyed rail. `.ig-reevaluate[data-order='held']
|
|
11
|
+
* .ig-viewer` reaches a layer-1 class — but only from INSIDE this surface's own
|
|
12
|
+
* root, and only for a state layer 1 does not model. The viewer draws the order
|
|
13
|
+
* it is handed; whether that order is the current one is a fact only the store
|
|
14
|
+
* knows, so the label and the greying belong to whoever knows it. Nothing here
|
|
15
|
+
* changes how the rail looks outside this surface.
|
|
16
|
+
*
|
|
17
|
+
* There is no transition and no animation, anywhere in this file. The design
|
|
18
|
+
* rejected the animated re-sort because rows moving under the cursor mean the
|
|
19
|
+
* next edit targets the wrong thing, and it rejected the toast because the only
|
|
20
|
+
* evidence the edit worked disappears before it is read. A stylesheet is a
|
|
21
|
+
* place both could creep back in.
|
|
22
|
+
*/
|
|
23
|
+
export declare const reevaluateStylesheet = "\n.ig-reevaluate {\n display: flex;\n flex-direction: column;\n gap: var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size);\n line-height: var(--ig-line-height);\n color: var(--ig-text-body);\n}\n\n/* Greyed one step, and never hidden: a stale order that is labelled is still\n the most useful thing on the screen.\n\n A FILTER, NOT A COLOUR, and that is the whole point of this rule. color on\n the rail greys almost nothing: the viewer's own stylesheet sets color\n directly on .ig-title, .ig-id and .ig-hold, and carries the stations\n and badges in background and border-color, none of which inherit at all.\n A specified value beats an inherited one, so the stale order would have kept\n its normal palette while this rule looked like it was doing something.\n\n The enumeration is the trap here, not the oversight: listing the descendants\n to override is the \"a static rule names one spelling of a capability\"\n class this repository has already paid for several times over, and it would\n go stale the first time layer 1 colours something new. filter applies to\n an element AND its whole subtree whatever properties that subtree sets, so\n a descendant added later is covered by construction. styles.test.ts pins\n both halves: that layer 1 really does colour its own descendants, and that\n this rule is not a bare color. */\n.ig-reevaluate[data-order='held'] .ig-viewer {\n filter: grayscale(1);\n}\n\n.ig-order-computing {\n margin: 0;\n color: var(--ig-text-muted);\n font-size: var(--ig-font-size-small);\n}\n\n.ig-change-summary {\n display: flex;\n gap: var(--ig-space);\n align-items: baseline;\n flex-wrap: wrap;\n}\n\n.ig-change-line {\n display: flex;\n align-items: baseline;\n}\n\n.ig-change-parts {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-wrap: wrap;\n /* The blast radius reads as ONE line. The gap is the separator, so no\n punctuation glyph is baked into the markup \u2014 that would be a second\n language choice on top of the words themselves. */\n gap: var(--ig-space);\n}\n\n.ig-change-part {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n}\n\n.ig-change-count {\n font-family: var(--ig-font-mono);\n color: var(--ig-text);\n}\n\n.ig-change-word {\n color: var(--ig-text-body);\n}\n\n.ig-change-unchanged {\n margin: 0;\n color: var(--ig-text-body);\n}\n\n.ig-change-dismiss {\n align-self: flex-start;\n background: var(--ig-surface-2);\n color: var(--ig-text-body);\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-tight) var(--ig-space);\n font-family: var(--ig-font-ui);\n font-size: var(--ig-font-size-small);\n cursor: pointer;\n}\n\n.ig-change-dismiss:focus-visible {\n outline: var(--ig-focus-ring) solid var(--ig-focus);\n outline-offset: var(--ig-space-tight);\n}\n\n.ig-delta-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-direction: column;\n gap: var(--ig-space-tight);\n}\n\n.ig-delta-chip {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n border: var(--ig-stroke) solid var(--ig-line);\n border-radius: var(--ig-radius);\n padding: var(--ig-space-tight);\n background: var(--ig-surface-2);\n}\n\n.ig-delta-member {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n}\n\n.ig-delta-key,\n.ig-delta-ref {\n font-family: var(--ig-font-mono);\n color: var(--ig-text-muted);\n}\n\n/* The count and its word are adjacent spans with no text between them, so\n without this they render as 2up. Same reason .ig-change-part has one. */\n.ig-delta-move {\n display: flex;\n gap: var(--ig-space-tight);\n align-items: baseline;\n}\n\n.ig-delta-move[data-direction='up'] .ig-change-count {\n color: var(--ig-station-ready);\n}\n\n.ig-delta-move[data-direction='down'] .ig-change-count {\n color: var(--ig-text-muted);\n}\n\n.ig-delta-readiness[data-readiness='promoted'] {\n color: var(--ig-station-ready);\n}\n\n.ig-delta-readiness[data-readiness='newly-held'] {\n color: var(--ig-station-held);\n}\n\n.ig-delta-presence {\n color: var(--ig-text-muted);\n}\n";
|
|
24
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/reevaluate/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,oBAAoB,2oIA8JhC,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The re-evaluate surface's structural stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* Same contract as the viewer's and the ladder's: layout, weight and state,
|
|
5
|
+
* never a value. Every colour, length and font is a `var(--ig-…)` the host's
|
|
6
|
+
* theme resolves, so a second theme keeps working here too, and
|
|
7
|
+
* `styles.test.ts` scans these bytes for a literal or an unresolvable token.
|
|
8
|
+
*
|
|
9
|
+
* IT ADDS SELECTORS RATHER THAN REDEFINING THEM, with one deliberate exception
|
|
10
|
+
* that is worth naming: the greyed rail. `.ig-reevaluate[data-order='held']
|
|
11
|
+
* .ig-viewer` reaches a layer-1 class — but only from INSIDE this surface's own
|
|
12
|
+
* root, and only for a state layer 1 does not model. The viewer draws the order
|
|
13
|
+
* it is handed; whether that order is the current one is a fact only the store
|
|
14
|
+
* knows, so the label and the greying belong to whoever knows it. Nothing here
|
|
15
|
+
* changes how the rail looks outside this surface.
|
|
16
|
+
*
|
|
17
|
+
* There is no transition and no animation, anywhere in this file. The design
|
|
18
|
+
* rejected the animated re-sort because rows moving under the cursor mean the
|
|
19
|
+
* next edit targets the wrong thing, and it rejected the toast because the only
|
|
20
|
+
* evidence the edit worked disappears before it is read. A stylesheet is a
|
|
21
|
+
* place both could creep back in.
|
|
22
|
+
*/
|
|
23
|
+
export const reevaluateStylesheet = `
|
|
24
|
+
.ig-reevaluate {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
gap: var(--ig-space);
|
|
28
|
+
font-family: var(--ig-font-ui);
|
|
29
|
+
font-size: var(--ig-font-size);
|
|
30
|
+
line-height: var(--ig-line-height);
|
|
31
|
+
color: var(--ig-text-body);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Greyed one step, and never hidden: a stale order that is labelled is still
|
|
35
|
+
the most useful thing on the screen.
|
|
36
|
+
|
|
37
|
+
A FILTER, NOT A COLOUR, and that is the whole point of this rule. color on
|
|
38
|
+
the rail greys almost nothing: the viewer's own stylesheet sets color
|
|
39
|
+
directly on .ig-title, .ig-id and .ig-hold, and carries the stations
|
|
40
|
+
and badges in background and border-color, none of which inherit at all.
|
|
41
|
+
A specified value beats an inherited one, so the stale order would have kept
|
|
42
|
+
its normal palette while this rule looked like it was doing something.
|
|
43
|
+
|
|
44
|
+
The enumeration is the trap here, not the oversight: listing the descendants
|
|
45
|
+
to override is the "a static rule names one spelling of a capability"
|
|
46
|
+
class this repository has already paid for several times over, and it would
|
|
47
|
+
go stale the first time layer 1 colours something new. filter applies to
|
|
48
|
+
an element AND its whole subtree whatever properties that subtree sets, so
|
|
49
|
+
a descendant added later is covered by construction. styles.test.ts pins
|
|
50
|
+
both halves: that layer 1 really does colour its own descendants, and that
|
|
51
|
+
this rule is not a bare color. */
|
|
52
|
+
.ig-reevaluate[data-order='held'] .ig-viewer {
|
|
53
|
+
filter: grayscale(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.ig-order-computing {
|
|
57
|
+
margin: 0;
|
|
58
|
+
color: var(--ig-text-muted);
|
|
59
|
+
font-size: var(--ig-font-size-small);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.ig-change-summary {
|
|
63
|
+
display: flex;
|
|
64
|
+
gap: var(--ig-space);
|
|
65
|
+
align-items: baseline;
|
|
66
|
+
flex-wrap: wrap;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.ig-change-line {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: baseline;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ig-change-parts {
|
|
75
|
+
list-style: none;
|
|
76
|
+
margin: 0;
|
|
77
|
+
padding: 0;
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-wrap: wrap;
|
|
80
|
+
/* The blast radius reads as ONE line. The gap is the separator, so no
|
|
81
|
+
punctuation glyph is baked into the markup — that would be a second
|
|
82
|
+
language choice on top of the words themselves. */
|
|
83
|
+
gap: var(--ig-space);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ig-change-part {
|
|
87
|
+
display: flex;
|
|
88
|
+
gap: var(--ig-space-tight);
|
|
89
|
+
align-items: baseline;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.ig-change-count {
|
|
93
|
+
font-family: var(--ig-font-mono);
|
|
94
|
+
color: var(--ig-text);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.ig-change-word {
|
|
98
|
+
color: var(--ig-text-body);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ig-change-unchanged {
|
|
102
|
+
margin: 0;
|
|
103
|
+
color: var(--ig-text-body);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.ig-change-dismiss {
|
|
107
|
+
align-self: flex-start;
|
|
108
|
+
background: var(--ig-surface-2);
|
|
109
|
+
color: var(--ig-text-body);
|
|
110
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
111
|
+
border-radius: var(--ig-radius);
|
|
112
|
+
padding: var(--ig-space-tight) var(--ig-space);
|
|
113
|
+
font-family: var(--ig-font-ui);
|
|
114
|
+
font-size: var(--ig-font-size-small);
|
|
115
|
+
cursor: pointer;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.ig-change-dismiss:focus-visible {
|
|
119
|
+
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
120
|
+
outline-offset: var(--ig-space-tight);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.ig-delta-list {
|
|
124
|
+
list-style: none;
|
|
125
|
+
margin: 0;
|
|
126
|
+
padding: 0;
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
gap: var(--ig-space-tight);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.ig-delta-chip {
|
|
133
|
+
display: flex;
|
|
134
|
+
gap: var(--ig-space-tight);
|
|
135
|
+
align-items: baseline;
|
|
136
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
137
|
+
border-radius: var(--ig-radius);
|
|
138
|
+
padding: var(--ig-space-tight);
|
|
139
|
+
background: var(--ig-surface-2);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.ig-delta-member {
|
|
143
|
+
display: flex;
|
|
144
|
+
gap: var(--ig-space-tight);
|
|
145
|
+
align-items: baseline;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.ig-delta-key,
|
|
149
|
+
.ig-delta-ref {
|
|
150
|
+
font-family: var(--ig-font-mono);
|
|
151
|
+
color: var(--ig-text-muted);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* The count and its word are adjacent spans with no text between them, so
|
|
155
|
+
without this they render as 2up. Same reason .ig-change-part has one. */
|
|
156
|
+
.ig-delta-move {
|
|
157
|
+
display: flex;
|
|
158
|
+
gap: var(--ig-space-tight);
|
|
159
|
+
align-items: baseline;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.ig-delta-move[data-direction='up'] .ig-change-count {
|
|
163
|
+
color: var(--ig-station-ready);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.ig-delta-move[data-direction='down'] .ig-change-count {
|
|
167
|
+
color: var(--ig-text-muted);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.ig-delta-readiness[data-readiness='promoted'] {
|
|
171
|
+
color: var(--ig-station-ready);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.ig-delta-readiness[data-readiness='newly-held'] {
|
|
175
|
+
color: var(--ig-station-held);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.ig-delta-presence {
|
|
179
|
+
color: var(--ig-text-muted);
|
|
180
|
+
}
|
|
181
|
+
`;
|
|
182
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/reevaluate/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8JnC,CAAC"}
|