@maple-kit/ui 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.
Files changed (173) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +9 -0
  3. package/README.md +39 -0
  4. package/dist/composer/actions.d.ts +15 -0
  5. package/dist/composer/actions.js +59 -0
  6. package/dist/composer/attachments.d.ts +33 -0
  7. package/dist/composer/attachments.js +166 -0
  8. package/dist/composer/badge.d.ts +13 -0
  9. package/dist/composer/badge.js +25 -0
  10. package/dist/composer/body.d.ts +13 -0
  11. package/dist/composer/body.js +119 -0
  12. package/dist/composer/composer.d.ts +23 -0
  13. package/dist/composer/composer.js +122 -0
  14. package/dist/composer/css.js +559 -0
  15. package/dist/composer/detail.d.ts +32 -0
  16. package/dist/composer/detail.js +102 -0
  17. package/dist/composer/emoji.d.ts +54 -0
  18. package/dist/composer/emoji.js +131 -0
  19. package/dist/composer/index.d.ts +15 -0
  20. package/dist/composer/index.js +15 -0
  21. package/dist/composer/inset.js +20 -0
  22. package/dist/composer/leave.d.ts +19 -0
  23. package/dist/composer/leave.js +34 -0
  24. package/dist/composer/peek.d.ts +21 -0
  25. package/dist/composer/peek.js +29 -0
  26. package/dist/composer/phrase.d.ts +27 -0
  27. package/dist/composer/phrase.js +30 -0
  28. package/dist/composer/picker-emoji.d.ts +34 -0
  29. package/dist/composer/picker-emoji.js +48 -0
  30. package/dist/composer/prompt.js +31 -0
  31. package/dist/composer/scope.d.ts +11 -0
  32. package/dist/composer/scope.js +16 -0
  33. package/dist/composer/target.d.ts +13 -0
  34. package/dist/composer/target.js +45 -0
  35. package/dist/context.d.ts +21 -0
  36. package/dist/context.js +16 -0
  37. package/dist/data.d.ts +52 -0
  38. package/dist/data.js +30 -0
  39. package/dist/icons/branch.d.ts +4 -0
  40. package/dist/icons/branch.js +8 -0
  41. package/dist/icons/cog.d.ts +4 -0
  42. package/dist/icons/cog.js +8 -0
  43. package/dist/icons/commit.d.ts +4 -0
  44. package/dist/icons/commit.js +5 -0
  45. package/dist/icons/crossfade.d.ts +15 -0
  46. package/dist/icons/crossfade.js +27 -0
  47. package/dist/icons/element.d.ts +4 -0
  48. package/dist/icons/element.js +5 -0
  49. package/dist/icons/icon.d.ts +24 -0
  50. package/dist/icons/icon.js +27 -0
  51. package/dist/icons/index.d.ts +13 -0
  52. package/dist/icons/index.js +13 -0
  53. package/dist/icons/noplace.d.ts +4 -0
  54. package/dist/icons/noplace.js +5 -0
  55. package/dist/icons/region.d.ts +4 -0
  56. package/dist/icons/region.js +8 -0
  57. package/dist/icons/smiley.d.ts +4 -0
  58. package/dist/icons/smiley.js +8 -0
  59. package/dist/icons/sparkle.d.ts +4 -0
  60. package/dist/icons/sparkle.js +8 -0
  61. package/dist/icons/target.d.ts +4 -0
  62. package/dist/icons/target.js +5 -0
  63. package/dist/icons/text.d.ts +4 -0
  64. package/dist/icons/text.js +5 -0
  65. package/dist/index.d.ts +11 -0
  66. package/dist/index.js +11 -0
  67. package/dist/island/account.d.ts +10 -0
  68. package/dist/island/account.js +52 -0
  69. package/dist/island/comments.d.ts +24 -0
  70. package/dist/island/comments.js +40 -0
  71. package/dist/island/content.d.ts +10 -0
  72. package/dist/island/content.js +26 -0
  73. package/dist/island/context.d.ts +58 -0
  74. package/dist/island/context.js +23 -0
  75. package/dist/island/css.d.ts +13 -0
  76. package/dist/island/css.js +1020 -0
  77. package/dist/island/drag.d.ts +10 -0
  78. package/dist/island/drag.js +77 -0
  79. package/dist/island/filters.d.ts +10 -0
  80. package/dist/island/filters.js +63 -0
  81. package/dist/island/header.d.ts +32 -0
  82. package/dist/island/header.js +47 -0
  83. package/dist/island/index.d.ts +18 -0
  84. package/dist/island/index.js +18 -0
  85. package/dist/island/island.d.ts +12 -0
  86. package/dist/island/island.js +111 -0
  87. package/dist/island/item.d.ts +12 -0
  88. package/dist/island/item.js +158 -0
  89. package/dist/island/language.d.ts +55 -0
  90. package/dist/island/language.js +125 -0
  91. package/dist/island/leaf.js +17 -0
  92. package/dist/island/list.d.ts +12 -0
  93. package/dist/island/list.js +31 -0
  94. package/dist/island/new-comment.d.ts +18 -0
  95. package/dist/island/new-comment.js +56 -0
  96. package/dist/island/settings.d.ts +10 -0
  97. package/dist/island/settings.js +134 -0
  98. package/dist/island/stagger.d.ts +12 -0
  99. package/dist/island/stagger.js +4 -0
  100. package/dist/island/time.d.ts +17 -0
  101. package/dist/island/time.js +29 -0
  102. package/dist/island/trigger.d.ts +10 -0
  103. package/dist/island/trigger.js +39 -0
  104. package/dist/language.d.ts +45 -0
  105. package/dist/language.js +66 -0
  106. package/dist/maple.d.ts +25 -0
  107. package/dist/maple.js +65 -0
  108. package/dist/marks/avatar.d.ts +16 -0
  109. package/dist/marks/avatar.js +36 -0
  110. package/dist/marks/css.d.ts +12 -0
  111. package/dist/marks/css.js +371 -0
  112. package/dist/marks/frame.d.ts +25 -0
  113. package/dist/marks/frame.js +53 -0
  114. package/dist/marks/geometry.d.ts +55 -0
  115. package/dist/marks/geometry.js +61 -0
  116. package/dist/marks/index.d.ts +14 -0
  117. package/dist/marks/index.js +14 -0
  118. package/dist/marks/label.d.ts +23 -0
  119. package/dist/marks/label.js +31 -0
  120. package/dist/marks/layer.d.ts +16 -0
  121. package/dist/marks/layer.js +194 -0
  122. package/dist/marks/leaf.d.ts +18 -0
  123. package/dist/marks/leaf.js +7 -0
  124. package/dist/marks/mark.d.ts +28 -0
  125. package/dist/marks/mark.js +43 -0
  126. package/dist/marks/nudge.d.ts +50 -0
  127. package/dist/marks/nudge.js +76 -0
  128. package/dist/marks/paint.d.ts +11 -0
  129. package/dist/marks/paint.js +19 -0
  130. package/dist/marks/placement.d.ts +24 -0
  131. package/dist/marks/placement.js +28 -0
  132. package/dist/marks/ring.d.ts +28 -0
  133. package/dist/marks/ring.js +85 -0
  134. package/dist/marks/shape.d.ts +21 -0
  135. package/dist/marks/shape.js +51 -0
  136. package/dist/notice/css.d.ts +11 -0
  137. package/dist/notice/css.js +74 -0
  138. package/dist/notice/index.d.ts +4 -0
  139. package/dist/notice/index.js +4 -0
  140. package/dist/notice/language.d.ts +15 -0
  141. package/dist/notice/language.js +14 -0
  142. package/dist/notice/notice.d.ts +14 -0
  143. package/dist/notice/notice.js +49 -0
  144. package/dist/part.d.ts +9 -0
  145. package/dist/part.js +11 -0
  146. package/dist/picker/css.d.ts +13 -0
  147. package/dist/picker/css.js +141 -0
  148. package/dist/picker/index.d.ts +6 -0
  149. package/dist/picker/index.js +6 -0
  150. package/dist/picker/language.d.ts +14 -0
  151. package/dist/picker/language.js +17 -0
  152. package/dist/picker/picker.d.ts +18 -0
  153. package/dist/picker/picker.js +164 -0
  154. package/dist/picker/session.d.ts +16 -0
  155. package/dist/picker/session.js +35 -0
  156. package/dist/picker/target.d.ts +23 -0
  157. package/dist/picker/target.js +37 -0
  158. package/dist/root.d.ts +42 -0
  159. package/dist/root.js +75 -0
  160. package/dist/shots.js +32 -0
  161. package/dist/slot.d.ts +28 -0
  162. package/dist/slot.js +52 -0
  163. package/dist/slots.d.ts +24 -0
  164. package/dist/slots.js +75 -0
  165. package/dist/stylesheet.d.ts +15 -0
  166. package/dist/stylesheet.js +188 -0
  167. package/dist/theme.d.ts +20 -0
  168. package/dist/theme.js +13 -0
  169. package/dist/tip.d.ts +40 -0
  170. package/dist/tip.js +82 -0
  171. package/dist/tokens.d.ts +28 -0
  172. package/dist/tokens.js +180 -0
  173. package/package.json +56 -0
package/dist/data.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import { CommentStatus } from "@maple-kit/core";
2
+ //#region src/data.d.ts
3
+ /**
4
+ * How a mark is drawn: fill says how far through a comment's life it is, so
5
+ * the leaf fills up rather than emptying out. Open is an outline, re-verify
6
+ * is half, resolved is full, and one never written is an outline too — in
7
+ * grey, which is what tells the two apart.
8
+ */
9
+ export type PartForm = "outline" | "partial" | "solid";
10
+ /** The confidence word a reviewer reads, and what the low fill keys off. */
11
+ export type PartConfidence = "certain" | "fair" | "strong" | "weak";
12
+ /** How sure Maple is that this author is who the comment says. */
13
+ export type PartProvenance = "client" | "guest" | "server";
14
+ /** Everything a part may say about itself. Every field is optional. */
15
+ export interface PartState {
16
+ readonly status?: CommentStatus;
17
+ readonly form?: PartForm;
18
+ readonly confidence?: PartConfidence;
19
+ readonly provenance?: PartProvenance;
20
+ readonly armed?: boolean;
21
+ /** False for a comment still being written, which is drawn in grey. */
22
+ readonly sent?: boolean;
23
+ }
24
+ /** The rendered attributes, ready to spread. Absent state produces no attribute. */
25
+ export type PartAttributes = Readonly<Record<string, string>>;
26
+ /** Turns state into the six attributes. The only place their names appear. */
27
+ export declare function dataAttributes(state: PartState): PartAttributes;
28
+ /**
29
+ * What a pointer is doing to a part, rather than what its comment is.
30
+ *
31
+ * These are the overlay's own, so they carry the `mk` prefix the wire states
32
+ * do not: nothing here is recorded, sent, or true of the comment — a mark is
33
+ * peeked because a row is hovered, and nudged because someone moved it.
34
+ */
35
+ export interface PointerState {
36
+ /** A row or the mark itself is under a pointer. Sticks to nothing. */
37
+ readonly peeked?: boolean;
38
+ /** Moved off what it was covering, and holding where it was put. */
39
+ readonly nudged?: boolean;
40
+ readonly dragging?: boolean;
41
+ }
42
+ /** The three attributes, ready to spread. Absent state produces no attribute. */
43
+ export declare function pointerAttributes(state: PointerState): PartAttributes;
44
+ /**
45
+ * Fill, edge and colour never compete: this decides fill alone. An unsent
46
+ * comment is an outline and so is an unpinned one, which never reached the
47
+ * page; their colour is what separates them from an open comment.
48
+ */
49
+ export declare function formFor(status: CommentStatus | undefined, sent?: boolean): PartForm;
50
+ /** The four confidence words, at the thresholds the tooltips quote. */
51
+ export declare function confidenceFor(value: number): PartConfidence;
52
+ //#endregion
package/dist/data.js ADDED
@@ -0,0 +1,30 @@
1
+ //#region src/data.ts
2
+ function dataAttributes(state) {
3
+ const attributes = {};
4
+ if (state.status) attributes["data-status"] = state.status;
5
+ if (state.form) attributes["data-form"] = state.form;
6
+ if (state.confidence) attributes["data-confidence"] = state.confidence;
7
+ if (state.provenance) attributes["data-provenance"] = state.provenance;
8
+ if (state.armed !== void 0) attributes["data-armed"] = String(state.armed);
9
+ if (state.sent !== void 0) attributes["data-sent"] = String(state.sent);
10
+ return attributes;
11
+ }
12
+ function pointerAttributes(state) {
13
+ const attributes = {};
14
+ if (state.peeked !== void 0) attributes["data-mk-peeked"] = String(state.peeked);
15
+ if (state.nudged !== void 0) attributes["data-mk-nudged"] = String(state.nudged);
16
+ if (state.dragging !== void 0) attributes["data-mk-dragging"] = String(state.dragging);
17
+ return attributes;
18
+ }
19
+ function formFor(status, sent = true) {
20
+ if (!sent) return "outline";
21
+ if (status === "resolved") return "solid";
22
+ return status === "needs_reverify" ? "partial" : "outline";
23
+ }
24
+ function confidenceFor(value) {
25
+ if (value >= .95) return "certain";
26
+ if (value >= .85) return "strong";
27
+ return value >= .65 ? "fair" : "weak";
28
+ }
29
+ //#endregion
30
+ export { confidenceFor, dataAttributes, formFor, pointerAttributes };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/branch.d.ts
3
+ export declare const BranchIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,8 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/branch.ts
3
+ const BranchIcon = createIcon({
4
+ d: "M5 3.4v9.2 M6.6 2.6a1.6 1.6 0 1 1-3.2 0 1.6 1.6 0 1 1 3.2 0 M6.6 13.4a1.6 1.6 0 1 1-3.2 0 1.6 1.6 0 1 1 3.2 0 M12.6 4.6a1.6 1.6 0 1 1-3.2 0 1.6 1.6 0 1 1 3.2 0 M11 6.2c0 2.6-6 1.8-6 5",
5
+ strokeWidth: 1.3
6
+ });
7
+ //#endregion
8
+ export { BranchIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/cog.d.ts
3
+ export declare const CogIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,8 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/cog.ts
3
+ const CogIcon = createIcon({
4
+ d: "M2.5 5.5h2.7 M8.8 5.5h4.7 M2.5 10.5h4.7 M10.8 10.5h2.7 M8.8 5.5a1.8 1.8 0 1 1-3.6 0 1.8 1.8 0 1 1 3.6 0 M10.8 10.5a1.8 1.8 0 1 1-3.6 0 1.8 1.8 0 1 1 3.6 0",
5
+ strokeWidth: 1.3
6
+ });
7
+ //#endregion
8
+ export { CogIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/commit.d.ts
3
+ export declare const CommitIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/commit.ts
3
+ const CommitIcon = createIcon({ d: "M2 8h3.4 M10.6 8H14 M10.6 8a2.6 2.6 0 1 1-5.2 0 2.6 2.6 0 1 1 5.2 0" });
4
+ //#endregion
5
+ export { CommitIcon };
@@ -0,0 +1,15 @@
1
+ import { ReactElement, ReactNode } from "react";
2
+ //#region src/icons/crossfade.d.ts
3
+ /** What a part hands the cross-fade: the icon, and what to call it. */
4
+ export interface IconCrossfadeProps {
5
+ /** Changing this starts a swap. Two icons with one name never cross-fade. */
6
+ readonly name: string;
7
+ readonly children: ReactNode;
8
+ readonly className?: string;
9
+ }
10
+ /**
11
+ * Derived state, set during render rather than in an effect: an effect would
12
+ * paint the new icon once at full opacity before the transition began.
13
+ */
14
+ export declare function IconCrossfade(props: IconCrossfadeProps): ReactElement;
15
+ //#endregion
@@ -0,0 +1,27 @@
1
+ import { createElement, useState } from "react";
2
+ //#region src/icons/crossfade.ts
3
+ function IconCrossfade(props) {
4
+ const next = {
5
+ name: props.name,
6
+ node: props.children
7
+ };
8
+ const [swap, setSwap] = useState({ current: next });
9
+ if (swap.current.name !== props.name) setSwap({
10
+ current: next,
11
+ previous: swap.current
12
+ });
13
+ const className = props.className ? `mk-icon-swap ${props.className}` : "mk-icon-swap";
14
+ const shown = swap.current.name === props.name ? swap.current : next;
15
+ return createElement("span", {
16
+ className,
17
+ onTransitionEnd: () => setSwap({ current: shown })
18
+ }, swap.previous ? frame(swap.previous, "out") : null, frame(shown, "in"));
19
+ }
20
+ function frame(shown, direction) {
21
+ return createElement("span", {
22
+ key: shown.name,
23
+ "data-mk-icon": direction
24
+ }, shown.node);
25
+ }
26
+ //#endregion
27
+ export { IconCrossfade };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/element.d.ts
3
+ export declare const ElementIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/element.ts
3
+ const ElementIcon = createIcon({ d: "M2.5 2.5h11v11h-11z M2.5 6h11 M6 2.5v11" });
4
+ //#endregion
5
+ export { ElementIcon };
@@ -0,0 +1,24 @@
1
+ import { ForwardRefExoticComponent, RefAttributes, SVGProps } from "react";
2
+ //#region src/icons/icon.d.ts
3
+ /** Icons are drawn at 13px unless a part asks for another size. */
4
+ export declare const ICON_SIZE = 13;
5
+ /** Anything an `<svg>` takes, plus the one size the parts vary. */
6
+ export interface IconProps extends Omit<SVGProps<SVGSVGElement>, "ref"> {
7
+ readonly size?: number;
8
+ }
9
+ /** What `createIcon` returns: a forwarding component, ref and className included. */
10
+ export type IconComponent = ForwardRefExoticComponent<IconProps & RefAttributes<SVGSVGElement>>;
11
+ /** The path, and the three things that vary between them. */
12
+ export interface IconSpec {
13
+ readonly d: string;
14
+ readonly strokeWidth?: number;
15
+ readonly dashArray?: string;
16
+ /**
17
+ * Filled rather than stroked: a stroked glyph at 14px is three hairlines with
18
+ * gaps between them, and reads as an outline of nothing in particular.
19
+ */
20
+ readonly filled?: boolean;
21
+ }
22
+ /** Builds one icon. Called once per module, so a bundler can drop the unused. */
23
+ export declare function createIcon(spec: IconSpec): IconComponent;
24
+ //#endregion
@@ -0,0 +1,27 @@
1
+ import { createElement, forwardRef } from "react";
2
+ //#region src/icons/icon.ts
3
+ const ICON_SIZE = 13;
4
+ function createIcon(spec) {
5
+ return forwardRef(function Icon(props, ref) {
6
+ const { size = 13, ...rest } = props;
7
+ return createElement("svg", {
8
+ "aria-hidden": true,
9
+ focusable: false,
10
+ ...rest,
11
+ ref,
12
+ width: size,
13
+ height: size,
14
+ viewBox: "0 0 16 16",
15
+ fill: spec.filled === true ? "currentColor" : "none",
16
+ stroke: spec.filled === true ? "none" : "currentColor",
17
+ strokeWidth: spec.strokeWidth ?? 1.4,
18
+ strokeLinecap: "round",
19
+ strokeLinejoin: "round"
20
+ }, createElement("path", {
21
+ d: spec.d,
22
+ ...spec.dashArray === void 0 ? {} : { strokeDasharray: spec.dashArray }
23
+ }));
24
+ });
25
+ }
26
+ //#endregion
27
+ export { ICON_SIZE, createIcon };
@@ -0,0 +1,13 @@
1
+ import { ICON_SIZE, IconComponent, IconProps, IconSpec, createIcon } from "./icon.js";
2
+ import { BranchIcon } from "./branch.js";
3
+ import { CogIcon } from "./cog.js";
4
+ import { CommitIcon } from "./commit.js";
5
+ import { IconCrossfade, IconCrossfadeProps } from "./crossfade.js";
6
+ import { ElementIcon } from "./element.js";
7
+ import { NoPlaceIcon } from "./noplace.js";
8
+ import { RegionIcon } from "./region.js";
9
+ import { SmileyIcon } from "./smiley.js";
10
+ import { SparkleIcon } from "./sparkle.js";
11
+ import { TargetIcon } from "./target.js";
12
+ import { TextIcon } from "./text.js";
13
+ export { BranchIcon, CogIcon, CommitIcon, ElementIcon, ICON_SIZE, type IconComponent, IconCrossfade, type IconCrossfadeProps, type IconProps, type IconSpec, NoPlaceIcon, RegionIcon, SmileyIcon, SparkleIcon, TargetIcon, TextIcon, createIcon };
@@ -0,0 +1,13 @@
1
+ import { ICON_SIZE, createIcon } from "./icon.js";
2
+ import { SparkleIcon } from "./sparkle.js";
3
+ import { SmileyIcon } from "./smiley.js";
4
+ import { IconCrossfade } from "./crossfade.js";
5
+ import { ElementIcon } from "./element.js";
6
+ import { RegionIcon } from "./region.js";
7
+ import { TextIcon } from "./text.js";
8
+ import { CogIcon } from "./cog.js";
9
+ import { BranchIcon } from "./branch.js";
10
+ import { CommitIcon } from "./commit.js";
11
+ import { NoPlaceIcon } from "./noplace.js";
12
+ import { TargetIcon } from "./target.js";
13
+ export { BranchIcon, CogIcon, CommitIcon, ElementIcon, ICON_SIZE, IconCrossfade, NoPlaceIcon, RegionIcon, SmileyIcon, SparkleIcon, TargetIcon, TextIcon, createIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/noplace.d.ts
3
+ export declare const NoPlaceIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/noplace.ts
3
+ const NoPlaceIcon = createIcon({ d: "M8 14.2c3.1-3.3 4.7-5.7 4.7-7.9A4.7 4.7 0 0 0 3.3 6.3c0 2.2 1.6 4.6 4.7 7.9Z M2.4 2.4 13.6 13.6" });
4
+ //#endregion
5
+ export { NoPlaceIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/region.d.ts
3
+ export declare const RegionIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,8 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/region.ts
3
+ const RegionIcon = createIcon({
4
+ d: "M2 4.5h12v7H2z",
5
+ dashArray: "3 2.4"
6
+ });
7
+ //#endregion
8
+ export { RegionIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/smiley.d.ts
3
+ export declare const SmileyIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,8 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/smiley.ts
3
+ const SmileyIcon = createIcon({
4
+ d: "M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1Zm0 1.5a5.5 5.5 0 1 1 0 11 5.5 5.5 0 0 1 0-11ZM5.9 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2Zm4.2 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2ZM4.9 9.4a.75.75 0 0 1 1 .3 2.45 2.45 0 0 0 4.2 0 .75.75 0 1 1 1.3.75 3.95 3.95 0 0 1-6.8 0 .75.75 0 0 1 .3-1.05Z",
5
+ filled: true
6
+ });
7
+ //#endregion
8
+ export { SmileyIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/sparkle.d.ts
3
+ export declare const SparkleIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,8 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/sparkle.ts
3
+ const SparkleIcon = createIcon({
4
+ d: "M6.4 2.2 7.5 5.4 10.7 6.5 7.5 7.6 6.4 10.8 5.3 7.6 2.1 6.5 5.3 5.4Z M11.6 9.4 12.2 11 13.8 11.6 12.2 12.2 11.6 13.8 11 12.2 9.4 11.6 11 11Z",
5
+ strokeWidth: 1.1
6
+ });
7
+ //#endregion
8
+ export { SparkleIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/target.d.ts
3
+ export declare const TargetIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/target.ts
3
+ const TargetIcon = createIcon({ d: "M8 2.6v10.8 M2.6 8h10.8 M11.4 8a3.4 3.4 0 1 1-6.8 0 3.4 3.4 0 1 1 6.8 0" });
4
+ //#endregion
5
+ export { TargetIcon };
@@ -0,0 +1,4 @@
1
+ import { IconComponent } from "./icon.js";
2
+ //#region src/icons/text.d.ts
3
+ export declare const TextIcon: IconComponent;
4
+ //#endregion
@@ -0,0 +1,5 @@
1
+ import { createIcon } from "./icon.js";
2
+ //#region src/icons/text.ts
3
+ const TextIcon = createIcon({ d: "M3 3.5h10 M8 3.5v9 M6 12.5h4" });
4
+ //#endregion
5
+ export { TextIcon };
@@ -0,0 +1,11 @@
1
+ import { MOTION_TOKENS, RADIUS_TOKENS, REDUCED_MOTION_TOKENS, RUNTIME_TOKENS, SHEET_BREAKPOINT_PX } from "./tokens.js";
2
+ import { AsChildError, AsChildProps, Slot, SlotProps, composeRefs, mergeProps } from "./slot.js";
3
+ import { MapleUiContextError, MapleUiContextValue, useMapleUi } from "./context.js";
4
+ import { PartAttributes, PartConfidence, PartForm, PartProvenance, PartState, PointerState, confidenceFor, dataAttributes, formFor, pointerAttributes } from "./data.js";
5
+ import { DETAIL_COPY, ORPHAN_LABELS, ORPHAN_ORDER, ORPHAN_SENTENCES, PROVENANCE_SENTENCES, RUNG_LABELS, STATUS_LABELS, STATUS_SENTENCES, orphanTitle, rungLabel } from "./language.js";
6
+ import { MapleRoot, MapleRootProps, ThemePreference } from "./root.js";
7
+ import { REVIEWER_SLOT_COUNT, SLOT_INK_PROPERTY, SLOT_PROPERTY, applyReviewerSlot, slotColor, slotInk } from "./slots.js";
8
+ import { OVERLAY_CSS, SCHEME_ATTRIBUTE } from "./stylesheet.js";
9
+ import { OverlayTheme, useOverlayScheme } from "./theme.js";
10
+ import { Tip, TipProps, tipSpot } from "./tip.js";
11
+ export { AsChildError, type AsChildProps, DETAIL_COPY, MOTION_TOKENS, MapleRoot, type MapleRootProps, MapleUiContextError, type MapleUiContextValue, ORPHAN_LABELS, ORPHAN_ORDER, ORPHAN_SENTENCES, OVERLAY_CSS, type OverlayTheme, PROVENANCE_SENTENCES, type PartAttributes, type PartConfidence, type PartForm, type PartProvenance, type PartState, type PointerState, RADIUS_TOKENS, REDUCED_MOTION_TOKENS, REVIEWER_SLOT_COUNT, RUNG_LABELS, RUNTIME_TOKENS, MapleRoot as Root, SCHEME_ATTRIBUTE, SHEET_BREAKPOINT_PX, SLOT_INK_PROPERTY, SLOT_PROPERTY, STATUS_LABELS, STATUS_SENTENCES, Slot, type SlotProps, type ThemePreference, Tip, type TipProps, applyReviewerSlot, composeRefs, confidenceFor, dataAttributes, formFor, mergeProps, orphanTitle, pointerAttributes, rungLabel, slotColor, slotInk, tipSpot, useMapleUi, useOverlayScheme };
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ import { MapleUiContextError, useMapleUi } from "./context.js";
2
+ import { confidenceFor, dataAttributes, formFor, pointerAttributes } from "./data.js";
3
+ import { DETAIL_COPY, ORPHAN_LABELS, ORPHAN_ORDER, ORPHAN_SENTENCES, PROVENANCE_SENTENCES, RUNG_LABELS, STATUS_LABELS, STATUS_SENTENCES, orphanTitle, rungLabel } from "./language.js";
4
+ import { MOTION_TOKENS, RADIUS_TOKENS, REDUCED_MOTION_TOKENS, RUNTIME_TOKENS, SHEET_BREAKPOINT_PX } from "./tokens.js";
5
+ import { OVERLAY_CSS, SCHEME_ATTRIBUTE } from "./stylesheet.js";
6
+ import { useOverlayScheme } from "./theme.js";
7
+ import { MapleRoot } from "./root.js";
8
+ import { AsChildError, Slot, composeRefs, mergeProps } from "./slot.js";
9
+ import { REVIEWER_SLOT_COUNT, SLOT_INK_PROPERTY, SLOT_PROPERTY, applyReviewerSlot, slotColor, slotInk } from "./slots.js";
10
+ import { Tip, tipSpot } from "./tip.js";
11
+ export { AsChildError, DETAIL_COPY, MOTION_TOKENS, MapleRoot, MapleUiContextError, ORPHAN_LABELS, ORPHAN_ORDER, ORPHAN_SENTENCES, OVERLAY_CSS, PROVENANCE_SENTENCES, RADIUS_TOKENS, REDUCED_MOTION_TOKENS, REVIEWER_SLOT_COUNT, RUNG_LABELS, RUNTIME_TOKENS, MapleRoot as Root, SCHEME_ATTRIBUTE, SHEET_BREAKPOINT_PX, SLOT_INK_PROPERTY, SLOT_PROPERTY, STATUS_LABELS, STATUS_SENTENCES, Slot, Tip, applyReviewerSlot, composeRefs, confidenceFor, dataAttributes, formFor, mergeProps, orphanTitle, pointerAttributes, rungLabel, slotColor, slotInk, tipSpot, useMapleUi, useOverlayScheme };
@@ -0,0 +1,10 @@
1
+ import { PartProps } from "../part.js";
2
+ import { ReactNode } from "react";
3
+ //#region src/island/account.d.ts
4
+ /** The row. Its children replace everything inside it. */
5
+ export interface AccountProps extends PartProps {
6
+ readonly children?: ReactNode;
7
+ }
8
+ /** The GitHub link, as one row of the settings panel. */
9
+ export declare const Account: import("react").ForwardRefExoticComponent<AccountProps & import("react").RefAttributes<HTMLDivElement>>;
10
+ //#endregion
@@ -0,0 +1,52 @@
1
+ import { cx, renderPart } from "../part.js";
2
+ import { ACCOUNT_COPY } from "./language.js";
3
+ import { createElement, forwardRef } from "react";
4
+ import { useGitHubLink, useMapleClient } from "@maple-kit/react";
5
+ //#region src/island/account.ts
6
+ const Account = forwardRef(function Account(props, ref) {
7
+ const { asChild, children, className, ...rest } = props;
8
+ const link = useGitHubLink();
9
+ const client = useMapleClient();
10
+ if (link.state === "unsupported") return null;
11
+ return renderPart("div", asChild, {
12
+ ...rest,
13
+ className: cx("mk-setting", className),
14
+ "data-mk-link": link.state,
15
+ ref
16
+ }, children ?? [createElement("span", { key: "said" }, createElement("span", { className: "mk-setting-name" }, ACCOUNT_COPY.name), createElement("span", { className: "mk-setting-hint" }, said(link)), code(link)), action(link, client)]);
17
+ });
18
+ function said(link) {
19
+ if (link.state === "linked") return ACCOUNT_COPY.linkedAs(login(link.login));
20
+ if (link.state === "linking") return ACCOUNT_COPY.linking;
21
+ if (link.state === "failed") return link.reason;
22
+ return ACCOUNT_COPY.unlinked;
23
+ }
24
+ function login(name) {
25
+ return name === void 0 ? void 0 : `@${name}`;
26
+ }
27
+ function code(link) {
28
+ if (link.state !== "linking") return null;
29
+ return createElement("span", {
30
+ key: "code",
31
+ className: "mk-acct-code"
32
+ }, createElement("code", null, link.userCode), createElement("a", {
33
+ href: link.verificationUri,
34
+ target: "_blank",
35
+ rel: "noreferrer noopener"
36
+ }, ACCOUNT_COPY.open));
37
+ }
38
+ function action(link, client) {
39
+ if (link.state === "linking") return null;
40
+ const linked = link.state === "linked";
41
+ const offer = link.state === "failed" ? ACCOUNT_COPY.retry : ACCOUNT_COPY.link;
42
+ const label = linked ? ACCOUNT_COPY.unlink : offer;
43
+ return createElement("button", {
44
+ key: "act",
45
+ type: "button",
46
+ className: "mk-acct-do",
47
+ ...linked ? { title: ACCOUNT_COPY.unlinkHint } : {},
48
+ onClick: () => void (linked ? client.unlinkGitHub() : client.linkGitHub())
49
+ }, label);
50
+ }
51
+ //#endregion
52
+ export { Account };
@@ -0,0 +1,24 @@
1
+ import { CommentFilter } from "@maple-kit/core/client";
2
+ import { Anchor, OrphanReason, Resolution } from "@maple-kit/core/anchor";
3
+ import { Comment } from "@maple-kit/core";
4
+ //#region src/island/comments.d.ts
5
+ /** The count beside one filter's pill. */
6
+ export type FilterCounts = Readonly<Record<CommentFilter, number>>;
7
+ /** Each comment's place on the branch, oldest first, keyed by id. */
8
+ export declare function numbersFor(comments: readonly Comment[]): ReadonlyMap<string, number>;
9
+ /**
10
+ * The live count beside every pill. `All` subtracts the resolved ones while
11
+ * they are hidden, because the list under it does too.
12
+ */
13
+ export declare function countsFor(comments: readonly Comment[], showResolved: boolean): FilterCounts;
14
+ /**
15
+ * Why this comment has no place on the page, asked of the page itself. An
16
+ * anchor that resolves again has no reason, and the row says nothing.
17
+ */
18
+ export declare function orphanReason(anchor: Anchor, root: ParentNode): OrphanReason | undefined;
19
+ /**
20
+ * What the cascade says about every anchor, in one pass. In default detail
21
+ * only the unpinned are asked: nothing else on the row depends on the answer.
22
+ */
23
+ export declare function resolutionsFor(comments: readonly Comment[], root: ParentNode, developer: boolean): ReadonlyMap<string, Resolution>;
24
+ //#endregion
@@ -0,0 +1,40 @@
1
+ import { ORPHAN_ORDER } from "../language.js";
2
+ import { matchesFilter } from "@maple-kit/core/client";
3
+ import { resolveAnchor } from "@maple-kit/core/anchor";
4
+ //#region src/island/comments.ts
5
+ function numbersFor(comments) {
6
+ const ordered = [...comments].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
7
+ return new Map(ordered.map((comment, index) => [comment.id, index + 1]));
8
+ }
9
+ function countsFor(comments, showResolved) {
10
+ const count = (filter) => comments.filter((comment) => matchesFilter(comment, filter)).length;
11
+ const resolved = count("resolved");
12
+ return {
13
+ all: showResolved ? comments.length : comments.length - resolved,
14
+ open: count("open"),
15
+ needs_reverify: count("needs_reverify"),
16
+ resolved,
17
+ unpinned: count("unpinned")
18
+ };
19
+ }
20
+ function orphanReason(anchor, root) {
21
+ const resolution = resolveAnchor(anchor, { root });
22
+ return resolution.status === "orphaned" ? resolution.reason : void 0;
23
+ }
24
+ function resolutionsFor(comments, root, developer) {
25
+ const found = /* @__PURE__ */ new Map();
26
+ for (const comment of comments) {
27
+ if (!developer && comment.status !== "orphaned") continue;
28
+ found.set(comment.id, resolveAnchor(comment.anchor, { root }));
29
+ }
30
+ return found;
31
+ }
32
+ function byReason(comments, reasonOf) {
33
+ const rank = (comment) => {
34
+ const reason = reasonOf(comment);
35
+ return reason === void 0 ? ORPHAN_ORDER.length : ORPHAN_ORDER.indexOf(reason);
36
+ };
37
+ return [...comments].sort((a, b) => rank(a) - rank(b));
38
+ }
39
+ //#endregion
40
+ export { byReason, countsFor, numbersFor, orphanReason, resolutionsFor };
@@ -0,0 +1,10 @@
1
+ import { PartProps } from "../part.js";
2
+ import { ReactNode } from "react";
3
+ //#region src/island/content.d.ts
4
+ /** The card. Everything the island shows when it is open goes inside it. */
5
+ export interface IslandContentProps extends PartProps {
6
+ readonly children?: ReactNode;
7
+ }
8
+ /** Mounted while the island is open, and through its exit. */
9
+ export declare const IslandContent: import("react").ForwardRefExoticComponent<IslandContentProps & import("react").RefAttributes<HTMLDivElement>>;
10
+ //#endregion
@@ -0,0 +1,26 @@
1
+ import { cx, renderPart } from "../part.js";
2
+ import { ISLAND_COPY } from "./language.js";
3
+ import { useIsland } from "./context.js";
4
+ import { forwardRef } from "react";
5
+ //#region src/island/content.ts
6
+ const PART = "<Maple.IslandContent>";
7
+ const IslandContent = forwardRef(function IslandContent(props, ref) {
8
+ const { asChild, children, className, ...rest } = props;
9
+ const island = useIsland(PART);
10
+ if (island.phase === "closed") return null;
11
+ const onAnimationEnd = (event) => {
12
+ if (island.phase === "closing" && event.target === event.currentTarget) island.settled();
13
+ };
14
+ return renderPart("div", asChild, {
15
+ role: "region",
16
+ ...rest,
17
+ id: island.contentId,
18
+ "aria-label": ISLAND_COPY.title,
19
+ "data-mk-phase": island.phase,
20
+ className: cx("mk-card mk-surface", className),
21
+ onAnimationEnd,
22
+ ref
23
+ }, children);
24
+ });
25
+ //#endregion
26
+ export { IslandContent };
@@ -0,0 +1,58 @@
1
+ import { OrphanReason, Resolution } from "@maple-kit/core/anchor";
2
+ import { Comment } from "@maple-kit/core";
3
+ //#region src/island/context.d.ts
4
+ /** Open, shut, or on its way out: a close animates before it unmounts. */
5
+ export type IslandPhase = "closed" | "closing" | "open";
6
+ /** What every part below `Maple.Island` reads. */
7
+ export interface IslandContextValue {
8
+ readonly phase: IslandPhase;
9
+ /** Opening is immediate; closing runs the exit and then unmounts. */
10
+ readonly setOpen: (open: boolean) => void;
11
+ /** Called by the card once its exit animation has finished. */
12
+ readonly settled: () => void;
13
+ /** Off by default. What it reveals is the developer detail, not the switch. */
14
+ readonly developer: boolean;
15
+ readonly setDeveloper: (on: boolean) => void;
16
+ /** The settings panel's, held here so Escape can shut the newest surface. */
17
+ readonly settingsOpen: boolean;
18
+ readonly setSettingsOpen: (open: boolean) => void;
19
+ /** Ties the pill to the card for assistive technology. */
20
+ readonly contentId: string;
21
+ /** Each comment's place on the branch, oldest first. */
22
+ readonly numbers: ReadonlyMap<string, number>;
23
+ /** Everything on the branch, whatever the filter says. */
24
+ readonly comments: readonly Comment[];
25
+ /** What the cascade says about each anchor, asked of the page as it is now. */
26
+ readonly resolutions: ReadonlyMap<string, Resolution>;
27
+ /** The comment a link or a mark asked to be looked at, for the row to mark. */
28
+ readonly selected: string | null;
29
+ /** Drag state, so the pill moves the island and the card stays where it is. */
30
+ readonly drag: DragHandlers;
31
+ }
32
+ /** What the pill spreads to become the island's handle. */
33
+ export interface DragHandlers {
34
+ /** A ref callback for the island itself, which is the thing that moves. */
35
+ readonly attach: (node: HTMLElement | null) => void;
36
+ readonly onPointerDown: (event: PointerEventLike) => void;
37
+ readonly onPointerMove: (event: PointerEventLike) => void;
38
+ readonly onPointerUp: (event: PointerEventLike) => void;
39
+ /** True once the pointer travelled far enough to be a drag, not a click. */
40
+ readonly moved: () => boolean;
41
+ }
42
+ /** The parts of a pointer event a drag needs. Structural, so it tests flat. */
43
+ export interface PointerEventLike {
44
+ readonly clientX: number;
45
+ readonly clientY: number;
46
+ readonly pointerId: number;
47
+ readonly currentTarget: EventTarget | null;
48
+ }
49
+ /** Why this comment has no place, out of what the cascade answered. */
50
+ export declare function reasonOf(resolutions: ReadonlyMap<string, Resolution>, id: string): OrphanReason | undefined;
51
+ /** Thrown by an island part rendered outside `<Maple.Island>`. */
52
+ export declare class IslandContextError extends Error {
53
+ readonly name = "IslandContextError";
54
+ constructor(part: string);
55
+ }
56
+ /** The island's state, or a readable error rather than a null. */
57
+ export declare function useIsland(part: string): IslandContextValue;
58
+ //#endregion
@@ -0,0 +1,23 @@
1
+ import { createContext, useContext } from "react";
2
+ //#region src/island/context.ts
3
+ function reasonOf(resolutions, id) {
4
+ const resolution = resolutions.get(id);
5
+ return resolution?.status === "orphaned" ? resolution.reason : void 0;
6
+ }
7
+ const IslandContext = createContext(null);
8
+ function listId(contentId) {
9
+ return `${contentId}-list`;
10
+ }
11
+ var IslandContextError = class extends Error {
12
+ name = "IslandContextError";
13
+ constructor(part) {
14
+ super(`${part} was rendered outside <Maple.Island>. Every island part needs one above it.`);
15
+ }
16
+ };
17
+ function useIsland(part) {
18
+ const value = useContext(IslandContext);
19
+ if (value === null) throw new IslandContextError(part);
20
+ return value;
21
+ }
22
+ //#endregion
23
+ export { IslandContext, IslandContextError, listId, reasonOf, useIsland };