@jxsuite/studio 5.7.0 → 6.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 (162) hide show
  1. package/dist/chunks/{2020-cs2sb9t1.js → 2020-nkxms0ay.js} +3 -3
  2. package/dist/chunks/adapter-m948ab5f.js +4 -0
  3. package/dist/chunks/{cf-account-picker-882a7ecm.js → cf-account-picker-n8hr38v7.js} +3 -3
  4. package/dist/chunks/cf-settings-356xdtne.js +4 -0
  5. package/dist/chunks/components-yk3t844e.js +4 -0
  6. package/dist/chunks/content-source-bawmyc09.js +4 -0
  7. package/dist/chunks/{convert-to-repeater-grfep2w8.js → convert-to-repeater-7wns8kf1.js} +3 -3
  8. package/dist/chunks/editor-6sc8nacq.js +4 -0
  9. package/dist/chunks/entry-commands-8ay9fh81.js +4 -0
  10. package/dist/chunks/{extension-sections-dp8endhx.js → extension-sections-na7rj3nr.js} +3 -3
  11. package/dist/chunks/file-ops-gye0qw56.js +4 -0
  12. package/dist/chunks/files-dmc2xvcq.js +4 -0
  13. package/dist/chunks/format-host-t76b53f8.js +4 -0
  14. package/dist/chunks/fs-events-cg4tpz06.js +4 -0
  15. package/dist/chunks/git-panel-yef7bshy.js +4 -0
  16. package/dist/chunks/{grid-view-5amhg604.js → grid-view-7tt4bxw1.js} +6 -6
  17. package/dist/chunks/iframe-host-tmz30gfp.js +4 -0
  18. package/dist/chunks/{index-9ydfe04y.js → index-gybvv7a6.js} +3 -3
  19. package/dist/chunks/index-nag78a9h.js +4 -0
  20. package/dist/chunks/{javascript-d9pqgc2p.js → javascript-rnvdp3k4.js} +2 -2
  21. package/dist/chunks/{jsonMode-800yvbem.js → jsonMode-zhwsprqk.js} +5 -5
  22. package/dist/chunks/jx-validate-3gbp5nkn.js +4 -0
  23. package/dist/chunks/layers-fvz99859.js +4 -0
  24. package/dist/chunks/layers-panel-gchmbf9p.js +4 -0
  25. package/dist/chunks/lit-html-9agdspkt.js +4 -0
  26. package/dist/chunks/media-picker-rhjvyy00.js +4 -0
  27. package/dist/chunks/menu-2e4y9j7b.js +4 -0
  28. package/dist/chunks/{monaco-binding-62dtmgbf.js → monaco-binding-2jnhjjvr.js} +3 -3
  29. package/dist/chunks/monaco-buffer-rp21359g.js +4 -0
  30. package/dist/chunks/{monaco-setup-tj13ndtm.js → monaco-setup-vhh7gayr.js} +3 -3
  31. package/dist/chunks/notify-h3www560.js +4 -0
  32. package/dist/chunks/platform-hz34wcd7.js +4 -0
  33. package/dist/chunks/publish-panel-exsmjzyj.js +4 -0
  34. package/dist/chunks/quick-search-pgaqeh0m.js +4 -0
  35. package/dist/chunks/references-2cgdxnb8.js +4 -0
  36. package/dist/chunks/right-panel-jf856w5w.js +4 -0
  37. package/dist/chunks/section-registry-jnf8r5gy.js +4 -0
  38. package/dist/chunks/studio-0f55h9ye.js +5 -0
  39. package/dist/chunks/{studio-hjbg8d5y.js → studio-0sqdhnew.js} +7 -7
  40. package/dist/chunks/{studio-1wvfxkyy.js → studio-0x3jyb8r.js} +4 -4
  41. package/dist/chunks/{studio-yr04mv2j.js → studio-19x1c75w.js} +4 -4
  42. package/dist/chunks/{studio-evwgp1ym.js → studio-2sqcndak.js} +4 -4
  43. package/dist/chunks/{studio-cvbkkfqb.js → studio-3aey7dd3.js} +4 -4
  44. package/dist/chunks/{studio-888knnkc.js → studio-3bpdkq2s.js} +4 -4
  45. package/dist/chunks/{studio-ceb34dxj.js → studio-47y6fbpf.js} +4 -4
  46. package/dist/chunks/{studio-c6w3tq7t.js → studio-4m3826v2.js} +4 -4
  47. package/dist/chunks/studio-4nx2dj1g.js +4 -0
  48. package/dist/chunks/{studio-p7c1agz0.js → studio-4xv5s47r.js} +5 -5
  49. package/dist/chunks/{studio-sxc0zvpt.js → studio-5g0ag7c0.js} +3 -3
  50. package/dist/chunks/{studio-semd1s8s.js → studio-5g4t8v6w.js} +4 -4
  51. package/dist/chunks/studio-5py436sf.js +5 -0
  52. package/dist/chunks/{studio-aje966s9.js → studio-77kt594t.js} +4 -4
  53. package/dist/chunks/{studio-56z7evx4.js → studio-8f87n763.js} +6 -6
  54. package/dist/chunks/studio-8mb00b84.js +5 -0
  55. package/dist/chunks/studio-8p51gq2h.js +6 -0
  56. package/dist/chunks/studio-954ds834.js +5 -0
  57. package/dist/chunks/{studio-xta2vxp6.js → studio-9ft45c83.js} +6 -6
  58. package/dist/chunks/studio-a2138x5k.js +7 -0
  59. package/dist/chunks/studio-a9yzstqj.js +5 -0
  60. package/dist/chunks/{studio-gp02nqnw.js → studio-acdksxx6.js} +4 -4
  61. package/dist/chunks/{studio-edbtvcd1.js → studio-anyrgzvb.js} +4 -4
  62. package/dist/chunks/{studio-dkn3x3hz.js → studio-ar8jcf2y.js} +4 -4
  63. package/dist/chunks/{studio-xry7tk3z.js → studio-bmn4mn9j.js} +5 -5
  64. package/dist/chunks/{studio-03wwfvyt.js → studio-cpxkgjrj.js} +4 -4
  65. package/dist/chunks/{studio-spf2skgc.js → studio-e7xxa0sj.js} +4 -4
  66. package/dist/chunks/{studio-01qza1n3.js → studio-ecaz25vk.js} +4 -4
  67. package/dist/chunks/{studio-5e9zsamh.js → studio-fzdywr6p.js} +6 -6
  68. package/dist/chunks/{studio-65fhspdd.js → studio-g5fmf0c1.js} +4 -4
  69. package/dist/chunks/studio-g7nse7zb.js +5 -0
  70. package/dist/chunks/studio-geq1ea6k.js +14 -0
  71. package/dist/chunks/{studio-n78gjfy8.js → studio-ghkb32r8.js} +4 -4
  72. package/dist/chunks/{studio-222rqyyc.js → studio-ghrhy2y7.js} +4 -4
  73. package/dist/chunks/{studio-a7xqhc3n.js → studio-grawhey1.js} +4 -4
  74. package/dist/chunks/{studio-eh0rac07.js → studio-h0xgswew.js} +4 -4
  75. package/dist/chunks/{studio-wma2c6g8.js → studio-h9c4p2tx.js} +4 -4
  76. package/dist/chunks/studio-jyzj5cxs.js +5 -0
  77. package/dist/chunks/{studio-x92tgnee.js → studio-mgx8yhnz.js} +31 -31
  78. package/dist/chunks/{studio-0scebvb9.js → studio-mpb04y1d.js} +5 -5
  79. package/dist/chunks/{studio-xy3tv3az.js → studio-n17mty64.js} +4 -4
  80. package/dist/chunks/{studio-gfn1kpxj.js → studio-nwh2eqsk.js} +5 -5
  81. package/dist/chunks/{studio-nt06yybj.js → studio-pxg4ap1e.js} +3 -3
  82. package/dist/chunks/{studio-zpnk016a.js → studio-q1h883bt.js} +5 -5
  83. package/dist/chunks/{studio-c6zdm25z.js → studio-q4tv82h7.js} +6 -6
  84. package/dist/chunks/{studio-st75kn99.js → studio-qbj760tx.js} +5 -5
  85. package/dist/chunks/{studio-y7jehjrp.js → studio-qpqa7vk3.js} +4 -4
  86. package/dist/chunks/{studio-j6gnhvaa.js → studio-qqz8e5gk.js} +4 -4
  87. package/dist/chunks/{studio-skzanb0k.js → studio-qvasen3f.js} +4 -4
  88. package/dist/chunks/studio-rggdb3hm.js +5 -0
  89. package/dist/chunks/{studio-4xppwncr.js → studio-sghy936h.js} +3 -3
  90. package/dist/chunks/{studio-9mqfamps.js → studio-skprc6ef.js} +4 -4
  91. package/dist/chunks/{studio-1x8x26k3.js → studio-tt2nactf.js} +4 -4
  92. package/dist/chunks/{studio-54g077x3.js → studio-txjjzrsm.js} +5 -5
  93. package/dist/chunks/{studio-f195h2hq.js → studio-tyasmc39.js} +4 -4
  94. package/dist/chunks/{studio-0bbxhhce.js → studio-v2bvmbjj.js} +4 -4
  95. package/dist/chunks/{studio-pwqfmt4p.js → studio-vk9ezads.js} +4 -4
  96. package/dist/chunks/{studio-fqq890ap.js → studio-vzacdfsc.js} +3 -3
  97. package/dist/chunks/{studio-zd4kayn2.js → studio-w4c0xmrw.js} +4 -4
  98. package/dist/chunks/{studio-tw7rre6s.js → studio-wfjqhhbk.js} +4 -4
  99. package/dist/chunks/{studio-tp642n5g.js → studio-wgh5kxpj.js} +4 -4
  100. package/dist/chunks/studio-xasj0796.js +5 -0
  101. package/dist/chunks/{studio-tzegmy4w.js → studio-y78s8r2n.js} +4 -4
  102. package/dist/chunks/{studio-7pgy3xaf.js → studio-z8w183sh.js} +4 -4
  103. package/dist/chunks/{studio-01kbbqg3.js → studio-zscd9ty4.js} +124 -124
  104. package/dist/chunks/{studio-mwxgyn9h.js → studio-zxp13sss.js} +6 -6
  105. package/dist/chunks/{studio-r3kaka4d.js → studio-zygnmm01.js} +4 -4
  106. package/dist/chunks/{tsMode-k9s9fcag.js → tsMode-gr0m4dzr.js} +5 -5
  107. package/dist/chunks/workspace-m15qtcqp.js +4 -0
  108. package/dist/chunks/{ws-client-0ja08haa.js → ws-client-nf61frr1.js} +3 -3
  109. package/dist/iframe-entry.js +3 -3
  110. package/dist/manifest.json +62 -62
  111. package/dist/studio.js +83 -83
  112. package/package.json +11 -11
  113. package/src/new-project/add-repo-modal.ts +459 -59
  114. package/src/platforms/cloud.ts +95 -18
  115. package/src/publish/pages-service.ts +7 -0
  116. package/src/publish/publish-panel.ts +16 -2
  117. package/src/surfaces/add-repo.json +721 -224
  118. package/src/surfaces/add-repo.ts +196 -31
  119. package/src/types.ts +42 -3
  120. package/src/ui/schema-form.ts +6 -2
  121. package/src/utils/project-dir.ts +24 -0
  122. package/dist/chunks/adapter-y5gdq19c.js +0 -4
  123. package/dist/chunks/cf-settings-20dznc3j.js +0 -4
  124. package/dist/chunks/components-q037dya7.js +0 -4
  125. package/dist/chunks/content-source-37x3vsap.js +0 -4
  126. package/dist/chunks/editor-j5sq149q.js +0 -4
  127. package/dist/chunks/entry-commands-c5h3nqck.js +0 -4
  128. package/dist/chunks/file-ops-937cvqk6.js +0 -4
  129. package/dist/chunks/files-tznwe1p1.js +0 -4
  130. package/dist/chunks/format-host-e2pjvd25.js +0 -4
  131. package/dist/chunks/fs-events-fv64ak3s.js +0 -4
  132. package/dist/chunks/git-panel-gb713ttc.js +0 -4
  133. package/dist/chunks/iframe-host-t819mcg5.js +0 -4
  134. package/dist/chunks/index-m0x5ztax.js +0 -4
  135. package/dist/chunks/jx-validate-zc9zp77s.js +0 -4
  136. package/dist/chunks/layers-4bsr82wz.js +0 -4
  137. package/dist/chunks/layers-panel-b6shnaax.js +0 -4
  138. package/dist/chunks/lit-html-cfn61dn7.js +0 -4
  139. package/dist/chunks/media-picker-ej0kdh1j.js +0 -4
  140. package/dist/chunks/menu-rtxf9chb.js +0 -4
  141. package/dist/chunks/monaco-buffer-nn4dtx27.js +0 -4
  142. package/dist/chunks/notify-ahs57a2z.js +0 -4
  143. package/dist/chunks/platform-v9xyfkbx.js +0 -4
  144. package/dist/chunks/publish-panel-bq36xcmj.js +0 -4
  145. package/dist/chunks/quick-search-zm00h9dh.js +0 -4
  146. package/dist/chunks/references-99ws0b0m.js +0 -4
  147. package/dist/chunks/right-panel-pq2f71q3.js +0 -4
  148. package/dist/chunks/section-registry-b2yzp9sw.js +0 -4
  149. package/dist/chunks/studio-0k9mvpgj.js +0 -14
  150. package/dist/chunks/studio-1a99w39s.js +0 -5
  151. package/dist/chunks/studio-693nhyky.js +0 -5
  152. package/dist/chunks/studio-aqmph6k4.js +0 -5
  153. package/dist/chunks/studio-c9d3pxf7.js +0 -5
  154. package/dist/chunks/studio-cxt150pj.js +0 -7
  155. package/dist/chunks/studio-e6re3rk1.js +0 -5
  156. package/dist/chunks/studio-frb0qbf7.js +0 -6
  157. package/dist/chunks/studio-gh97gngt.js +0 -5
  158. package/dist/chunks/studio-nbxqcgvf.js +0 -5
  159. package/dist/chunks/studio-t1eedsyx.js +0 -4
  160. package/dist/chunks/studio-vavmwshr.js +0 -5
  161. package/dist/chunks/studio-xk0z6msk.js +0 -5
  162. package/dist/chunks/workspace-b69mgm0e.js +0 -4
@@ -1,19 +1,36 @@
1
1
  {
2
2
  "$schema": "https://jxsuite.com/schema/v1",
3
3
  "$id": "StudioAddRepo",
4
- "$description": "The repository picker: every repo the platform's account link can reach, filtered by name, and one of them adopted as a Jx project. Two flows share it — Add existing repository, and Open Project on a platform whose projects ARE repositories — so the headline is state rather than text. A `jx-dialog`, so the platform owns modality, Escape, focus restoration and the backdrop, which is what retired the `sp-underlay` this surface used to paint beside a fixed card and the `z-index: 1000` that card needed to climb back out from under its own scrim. There is no confirming button: each row commits itself, because a picker whose answer is one of N rows has N answers rather than one. Nothing here knows what `not_jx_project` means, which permission counts as write, or that a Jx-tagged repository sorts first — `new-project/add-repo-modal.ts` keeps the listing, the ordering and the adoption, and hands over rows that are already strings and booleans.",
4
+ "$description": "The repository picker: every repository the platform's account link can reach, narrowed by name and account, and — once one is chosen — the folders it holds a project.json in, so a project that lives in a subfolder opens as itself. Two flows share it — Add existing repository, and Open Project on a platform whose projects ARE repositories — so the headline and the primary answer are state rather than text. A `jx-dialog`, so the platform owns modality, Escape, focus restoration and the backdrop. Choosing is two steps now, a repository and then its folder, so the dialog has a confirming button again; a double-click on a row still opens it in one gesture when the folder is unambiguous. Nothing here knows what `not_jx_project` means, which permission counts as write, which folder to preselect or that a Jx-tagged repository sorts first — `new-project/add-repo-modal.ts` keeps the listing, the ordering, the scan and the adoption, and hands over rows that are already strings and booleans.",
5
5
  "tagName": "jx-dialog",
6
6
  "$props": {
7
7
  "headline": {
8
8
  "$ref": "#/state/title"
9
9
  },
10
- "confirmLabel": "",
10
+ "confirmLabel": {
11
+ "$ref": "#/state/confirmLabel"
12
+ },
13
+ "confirmDisabled": {
14
+ "$ref": "#/state/confirmDisabled"
15
+ },
11
16
  "cancelLabel": "Cancel",
12
- "size": "md"
17
+ "size": "xl"
13
18
  },
14
19
  "attributes": {
15
20
  "part": "add-repo"
16
21
  },
22
+ "onconfirm": {
23
+ "$prototype": "Function",
24
+ "body": [
25
+ {
26
+ "operator": "call",
27
+ "target": {
28
+ "$ref": "#/state/confirm"
29
+ },
30
+ "value": []
31
+ }
32
+ ]
33
+ },
17
34
  "oncancel": {
18
35
  "$prototype": "Function",
19
36
  "body": [
@@ -39,85 +56,142 @@
39
56
  ]
40
57
  },
41
58
  "style": {
42
- "$description": "Seventeen `.add-repo-*` rules in `styles/overlays.css` become the parts below, and four of them do not travel: `.add-repo-modal .new-project-modal-body` inherited a fixed card, a scroll body and a border from `.new-project-modal`, and a modal `<dialog>` is every one of those; `.add-repo-refresh` and its hover and disabled variants drew a button by hand, and the refresh is a `jx-button` now. The row's own `font-size: 13px` goes with them: a `<button>` does not inherit type, which is what `font: inherit` is for, and what it now inherits is the dialog's own body size rather than a number this surface picked. Six token repairs travel with the rest — `--spectrum-font-size-50` and `--spectrum-font-size-75` resolve only inside `<sp-theme>`, and a document mounted in the dialog layer is outside it, so every one of them would silently have taken its hard-coded fallback — and the two links lose the hard-coded blue they carried as a fallback behind `var(--accent)`, which is the same bug written the other way round.",
43
- "& [part=\"picker\"]": {
59
+ "$description": "The dialog is wide enough for two panes — the repositories on the left, the chosen repository's projects on the right — and the PANES scroll, never the dialog: `jx-dialog` pins its header and footer and scrolls its body, and this surface turns the body into a column the picker fills, so the filter above the lists, the summary under them and the access footer at the bottom all stay on screen however long a list is. That is what retired the two scrollbars the old picker drew side by side, its own 320px list inside a dialog that also scrolled. Below 40rem the panes stack.",
60
+ "& > [part=\"dialog\"] > [part=\"body\"]": {
61
+ "$description": "The kit's body scrolls by default; here the picker is the body's only child and does its own scrolling inside two panes, so the body becomes the column it fills.",
44
62
  "display": "flex",
45
63
  "flexDirection": "column",
46
- "gap": "var(--jx-space-3)"
64
+ "overflow": "hidden"
47
65
  },
48
- "& [part=\"list\"]": {
49
- "$description": "The list scrolls, not the dialog. `jx-dialog` already scrolls its own body, so a cap here looks redundant — it is not: the filter above the list and the access footer below it are the two things that widen a listing that is missing what the reader came for, and a dialog that scrolls as one takes both of them off screen exactly when the list is long enough to need them.",
66
+ "& [part=\"picker\"]": {
50
67
  "display": "flex",
51
68
  "flexDirection": "column",
52
- "maxHeight": "320px",
53
- "overflowY": "auto"
69
+ "gap": "var(--jx-space-3)",
70
+ "flex": "0 1 30rem",
71
+ "minHeight": "0",
72
+ "containerType": "inline-size",
73
+ "containerName": "add-repo"
54
74
  },
55
- "& [part=\"row\"]": {
56
- "$description": "A whole row is the button, because the answer is the repository rather than a control inside it. `baseline` rather than `center`: the name and the metadata beside it are different sizes, and aligning their boxes leaves the two strings visibly off each other.",
75
+ "& [part=\"toolbar\"]": {
57
76
  "display": "flex",
58
- "alignItems": "baseline",
77
+ "alignItems": "center",
78
+ "gap": "var(--jx-space-2)",
79
+ "flex": "none"
80
+ },
81
+ "& [part=\"filter\"]": {
82
+ "flex": "1 1 auto",
83
+ "minWidth": "0"
84
+ },
85
+ "& [part=\"owner\"]": {
86
+ "flex": "0 0 12rem"
87
+ },
88
+ "& [part=\"owner-slot\"], & [part=\"list-slot\"], & [part=\"detail-slot\"], & [part=\"locations-slot\"], & [part=\"failure-slot\"], & [part=\"access-slot\"], & [part=\"tag-slot\"], & [part=\"private-slot\"]": {
89
+ "display": "contents"
90
+ },
91
+ "& [part=\"panes\"]": {
92
+ "display": "grid",
93
+ "gridTemplateColumns": "minmax(0, 1fr) minmax(0, 1fr)",
59
94
  "gap": "var(--jx-space-3)",
60
- "width": "100%",
61
- "padding": "var(--jx-space-2) var(--jx-space-3)",
62
- "background": "none",
63
- "border": "none",
95
+ "flex": "1 1 auto",
96
+ "minHeight": "0"
97
+ },
98
+ "& [part=\"repos\"], & [part=\"detail\"]": {
99
+ "$description": "Each pane is a framed box of its own height that scrolls its own content, so choosing a repository far down the list never scrolls its projects out of view.",
100
+ "display": "flex",
101
+ "flexDirection": "column",
102
+ "minHeight": "0",
103
+ "border": "1px solid var(--border)",
64
104
  "borderRadius": "var(--radius)",
65
- "font": "inherit",
66
- "color": "var(--fg)",
67
- "cursor": "pointer",
68
- "textAlign": "left",
69
- "&:hover:not([disabled])": {
70
- "background": "var(--hover-bg)"
71
- },
72
- "&[disabled]": {
73
- "$description": "Every row goes quiet while any one of them is importing: one adoption at a time, and the row that is running says so itself rather than the list going grey around it.",
74
- "opacity": "0.6",
75
- "cursor": "default"
76
- }
105
+ "overflow": "hidden"
77
106
  },
78
- "& [part=\"name\"]": {
79
- "color": "var(--accent)"
107
+ "& [part=\"repo-list\"]": {
108
+ "flex": "1 1 auto",
109
+ "minHeight": "0",
110
+ "overflowY": "auto",
111
+ "padding": "var(--jx-space-1)"
80
112
  },
81
- "& [part=\"meta\"]": {
113
+ "& [part=\"location-list\"]": {
114
+ "margin": "0 calc(-1 * var(--jx-space-2))"
115
+ },
116
+ "& [part=\"detail-body\"]": {
82
117
  "display": "flex",
83
- "alignItems": "baseline",
84
- "gap": "var(--jx-space-2)",
118
+ "flexDirection": "column",
119
+ "gap": "var(--jx-space-3)",
120
+ "flex": "1 1 auto",
121
+ "minHeight": "0",
122
+ "overflowY": "auto",
123
+ "padding": "var(--jx-space-3)"
124
+ },
125
+ "& [part=\"detail-head\"]": {
126
+ "display": "flex",
127
+ "flexDirection": "column",
128
+ "gap": "var(--jx-space-1)",
129
+ "flex": "none",
130
+ "minWidth": "0"
131
+ },
132
+ "& [part=\"detail-name\"]": {
133
+ "fontWeight": "600",
134
+ "overflow": "hidden",
135
+ "textOverflow": "ellipsis",
136
+ "whiteSpace": "nowrap"
137
+ },
138
+ "& [part=\"detail-meta\"]": {
85
139
  "fontSize": "var(--jx-text-sm)",
86
140
  "color": "var(--fg-dim)"
87
141
  },
142
+ "& [part=\"folder-row\"]": {
143
+ "flex": "none"
144
+ },
145
+ "& [part=\"repo\"] [part=\"description\"], & [part=\"location\"] [part=\"description\"]": {
146
+ "$description": "The note gives way before the name does: a repository is found by its name, and a branch or a path cut short is still recognisable where a name cut short is not.",
147
+ "flexShrink": "4"
148
+ },
149
+ "& [part=\"badges\"]": {
150
+ "display": "inline-flex",
151
+ "gap": "var(--jx-space-1)"
152
+ },
88
153
  "& [part=\"badge\"]": {
89
154
  "padding": "0 var(--jx-space-2)",
90
- "border": "1px solid var(--border)",
91
- "borderRadius": "var(--jx-radius-lg)"
92
- },
93
- "& [part=\"busy\"]": {
94
- "$description": "Pushed to the far end of the row it belongs to, so \"Importing…\" reads as this repository's state rather than as another piece of its metadata.",
95
- "marginLeft": "auto",
96
- "fontSize": "var(--jx-text-sm)",
97
- "color": "var(--fg-dim)"
155
+ "border": "1px solid currentColor",
156
+ "borderRadius": "var(--jx-radius-lg)",
157
+ "fontSize": "var(--jx-text-xs)",
158
+ "opacity": "0.8"
98
159
  },
99
- "& [part=\"empty\"]": {
160
+ "& [part=\"empty\"], & [part=\"note\"]": {
100
161
  "margin": "0",
101
162
  "padding": "var(--jx-space-4) var(--jx-space-3)",
102
163
  "fontSize": "var(--jx-text-md)",
103
164
  "color": "var(--fg-dim)"
104
165
  },
166
+ "& [part=\"note\"]": {
167
+ "padding": "0"
168
+ },
169
+ "& [part=\"summary\"]": {
170
+ "$description": "What confirming will do, in words: which repository, which folder, which branch. Polite and live, because the arrows in both fields change it without moving focus, and this is how a reader who cannot see the panes hears where they are.",
171
+ "margin": "0",
172
+ "flex": "none",
173
+ "minHeight": "var(--jx-leading-md)",
174
+ "fontSize": "var(--jx-text-sm)",
175
+ "color": "var(--fg-dim)"
176
+ },
105
177
  "& [part=\"install\"], & [part=\"access-link\"]": {
106
178
  "color": "var(--accent)",
107
179
  "textDecoration": "underline"
108
180
  },
109
181
  "& [part=\"failure\"]": {
110
- "$description": "The refusal from the last adoption, said above the list the reader is still looking at, because the list survives it: a repository with no readable project.json is a fact about that repository, and the ones beside it are still on offer. It is `failure` rather than `error` because `jx-textfield` draws a `[part=\"error\"]` of its own inside this same tree — the kit is light DOM, so a scoped rule on that name would style the filter field's error line too.",
182
+ "$description": "The refusal from the last adoption, said above the footer the reader is still looking at, because the panes survive it: a folder with no readable project.json is a fact about that folder, and the rest are still on offer. It is `failure` rather than `error` because `jx-textfield` draws a `[part=\"error\"]` of its own inside this same tree.",
111
183
  "margin": "0",
184
+ "flex": "none",
112
185
  "fontSize": "var(--jx-text-md)",
113
186
  "color": "var(--danger)"
114
187
  },
115
188
  "& [part=\"access\"]": {
116
- "$description": "The listing is bounded by what the Jx Suite GitHub App was granted, so the dialog always offers a way out of that boundary rather than only saying the list is short. `center`, not `baseline`: the `Refresh` beside the note is a small kit button, and a small kit control is layout-contained so its outset hit area adds nothing to a scrolling ancestor's overflow, which leaves it with no baseline to export; a baseline row would synthesise one from its bottom edge and drop the note and the links onto it. surface-baseline-rows.test.ts holds the rule for every surface.",
189
+ "$description": "The listing is bounded by what the Jx Suite GitHub App was granted, so the dialog always offers a way out of that boundary rather than only saying the list is short. `center`, not `baseline`: a small kit button exports no baseline (surface-baseline-rows.test.ts).",
117
190
  "display": "flex",
118
191
  "flexWrap": "wrap",
119
192
  "alignItems": "center",
120
193
  "gap": "var(--jx-space-2)",
194
+ "flex": "none",
121
195
  "paddingTop": "var(--jx-space-3)",
122
196
  "borderTop": "1px solid var(--border)",
123
197
  "fontSize": "var(--jx-text-sm)",
@@ -130,6 +204,15 @@
130
204
  "display": "flex",
131
205
  "flexWrap": "wrap",
132
206
  "gap": "var(--jx-space-3)"
207
+ },
208
+ "@container add-repo (max-width: 40rem)": {
209
+ "& [part=\"panes\"]": {
210
+ "gridTemplateColumns": "minmax(0, 1fr)",
211
+ "gridTemplateRows": "minmax(0, 1fr) minmax(0, 1fr)"
212
+ },
213
+ "& [part=\"owner\"]": {
214
+ "flexBasis": "9rem"
215
+ }
133
216
  }
134
217
  },
135
218
  "children": [
@@ -140,235 +223,649 @@
140
223
  },
141
224
  "children": [
142
225
  {
143
- "tagName": "jx-textfield",
226
+ "tagName": "div",
144
227
  "attributes": {
145
- "part": "filter"
146
- },
147
- "$props": {
148
- "label": "Filter repositories",
149
- "placeholder": "Filter repositories…",
150
- "size": "sm",
151
- "value": {
152
- "$ref": "#/state/filter"
153
- }
228
+ "part": "toolbar"
154
229
  },
155
- "oninput": {
156
- "$prototype": "Function",
157
- "body": [
158
- {
159
- "operator": "call",
160
- "target": {
161
- "$ref": "#/state/setFilter"
162
- },
163
- "value": [
230
+ "children": [
231
+ {
232
+ "tagName": "jx-textfield",
233
+ "attributes": {
234
+ "part": "filter"
235
+ },
236
+ "$props": {
237
+ "label": "Filter repositories",
238
+ "placeholder": "Filter repositories…",
239
+ "type": "search",
240
+ "size": "sm",
241
+ "value": {
242
+ "$ref": "#/state/filter"
243
+ }
244
+ },
245
+ "oninput": {
246
+ "$prototype": "Function",
247
+ "body": [
248
+ {
249
+ "operator": "call",
250
+ "target": {
251
+ "$ref": "#/state/setFilter"
252
+ },
253
+ "value": [
254
+ {
255
+ "$ref": "event#/target/value"
256
+ }
257
+ ]
258
+ }
259
+ ]
260
+ },
261
+ "onkeydown": {
262
+ "$prototype": "Function",
263
+ "body": [
164
264
  {
165
- "$ref": "event#/target/value"
265
+ "$switch": {
266
+ "$ref": "event#/key"
267
+ },
268
+ "cases": {
269
+ "ArrowDown": [
270
+ {
271
+ "preventDefault": true
272
+ },
273
+ {
274
+ "operator": "call",
275
+ "target": {
276
+ "$ref": "#/state/move"
277
+ },
278
+ "value": [1]
279
+ }
280
+ ],
281
+ "ArrowUp": [
282
+ {
283
+ "preventDefault": true
284
+ },
285
+ {
286
+ "operator": "call",
287
+ "target": {
288
+ "$ref": "#/state/move"
289
+ },
290
+ "value": [-1]
291
+ }
292
+ ],
293
+ "Enter": [
294
+ {
295
+ "preventDefault": true
296
+ },
297
+ {
298
+ "operator": "call",
299
+ "target": {
300
+ "$ref": "#/state/confirm"
301
+ },
302
+ "value": []
303
+ }
304
+ ]
305
+ }
166
306
  }
167
307
  ]
168
308
  }
169
- ]
170
- }
171
- },
172
- {
173
- "tagName": "div",
174
- "attributes": {
175
- "part": "body-slot",
176
- "role": "none"
177
- },
178
- "style": {
179
- "display": "contents"
180
- },
181
- "$switch": {
182
- "$ref": "#/state/listState"
183
- },
184
- "cases": {
185
- "loading": {
186
- "tagName": "p",
187
- "attributes": {
188
- "part": "empty"
189
- },
190
- "textContent": "Loading repositories…"
191
309
  },
192
- "empty-filter": {
193
- "tagName": "p",
310
+ {
311
+ "tagName": "div",
194
312
  "attributes": {
195
- "part": "empty"
313
+ "part": "owner-slot",
314
+ "role": "none"
196
315
  },
197
- "textContent": "No repositories match the filter."
198
- },
199
- "empty-write": {
200
- "tagName": "p",
201
- "attributes": {
202
- "part": "empty"
316
+ "style": {
317
+ "display": "contents"
203
318
  },
204
- "textContent": "No repositories with write access. Widen the Jx Suite GitHub App's repository access below, or ask a repository admin for write access."
205
- },
206
- "empty-install": {
207
- "tagName": "p",
208
- "attributes": {
209
- "part": "empty"
319
+ "$switch": {
320
+ "$ref": "#/state/hasOwners"
210
321
  },
211
- "children": [
212
- {
213
- "tagName": "span",
214
- "textContent": "No repositories are reachable yet. "
215
- },
216
- {
217
- "tagName": "a",
322
+ "cases": {
323
+ "true": {
324
+ "tagName": "jx-select",
218
325
  "attributes": {
219
- "part": "install",
220
- "href": "${state.installUrl}",
221
- "target": "_blank",
222
- "rel": "noreferrer"
326
+ "part": "owner"
223
327
  },
224
- "textContent": "Install the Jx Suite GitHub App"
225
- },
226
- {
227
- "tagName": "span",
228
- "textContent": " to grant repository access, then use Refresh below."
328
+ "$props": {
329
+ "label": "Account",
330
+ "size": "sm",
331
+ "options": {
332
+ "$ref": "#/state/owners"
333
+ },
334
+ "value": {
335
+ "$ref": "#/state/owner"
336
+ }
337
+ },
338
+ "onchange": {
339
+ "$prototype": "Function",
340
+ "body": [
341
+ {
342
+ "operator": "call",
343
+ "target": {
344
+ "$ref": "#/state/setOwner"
345
+ },
346
+ "value": [
347
+ {
348
+ "$ref": "event#/target/value"
349
+ }
350
+ ]
351
+ }
352
+ ]
353
+ }
229
354
  }
230
- ]
231
- },
232
- "empty-none": {
233
- "tagName": "p",
234
- "attributes": {
235
- "part": "empty"
236
- },
237
- "textContent": "No repositories are reachable. Install the GitHub App (or widen its repository access) and try again."
238
- },
239
- "listed": {
240
- "tagName": "div",
355
+ }
356
+ }
357
+ ]
358
+ },
359
+ {
360
+ "tagName": "div",
361
+ "attributes": {
362
+ "part": "panes"
363
+ },
364
+ "children": [
365
+ {
366
+ "tagName": "section",
241
367
  "attributes": {
242
- "part": "list"
368
+ "part": "repos",
369
+ "aria-label": "Repositories"
243
370
  },
244
371
  "children": [
245
372
  {
246
- "$prototype": "Array",
247
- "items": {
248
- "$ref": "#/state/rows"
373
+ "tagName": "div",
374
+ "attributes": {
375
+ "part": "list-slot",
376
+ "role": "none"
249
377
  },
250
- "key": {
251
- "$ref": "$map/item/fullName"
378
+ "style": {
379
+ "display": "contents"
252
380
  },
253
- "map": {
254
- "tagName": "button",
255
- "attributes": {
256
- "part": "row",
257
- "type": "button",
258
- "data-repo": "${$map.item.fullName}",
259
- "title": "${$map.item.fullName}",
260
- "disabled": {
261
- "$ref": "$map/item/disabled"
262
- }
381
+ "$switch": {
382
+ "$ref": "#/state/listState"
383
+ },
384
+ "cases": {
385
+ "loading": {
386
+ "tagName": "p",
387
+ "attributes": {
388
+ "part": "empty"
389
+ },
390
+ "textContent": "Loading repositories…"
391
+ },
392
+ "empty-filter": {
393
+ "tagName": "p",
394
+ "attributes": {
395
+ "part": "empty"
396
+ },
397
+ "textContent": "No repositories match the filter."
398
+ },
399
+ "empty-write": {
400
+ "tagName": "p",
401
+ "attributes": {
402
+ "part": "empty"
403
+ },
404
+ "textContent": "Repositories you can write to are listed here. Widen the Jx Suite GitHub App's repository access below, or ask a repository admin for write access."
263
405
  },
264
- "onclick": {
265
- "$prototype": "Function",
266
- "body": [
406
+ "empty-install": {
407
+ "tagName": "p",
408
+ "attributes": {
409
+ "part": "empty"
410
+ },
411
+ "children": [
267
412
  {
268
- "operator": "call",
269
- "target": {
270
- "$ref": "#/state/choose"
413
+ "tagName": "span",
414
+ "textContent": "Repositories the Jx Suite GitHub App can reach are listed here. "
415
+ },
416
+ {
417
+ "tagName": "a",
418
+ "attributes": {
419
+ "part": "install",
420
+ "href": "${state.installUrl}",
421
+ "target": "_blank",
422
+ "rel": "noreferrer"
271
423
  },
272
- "value": [
273
- {
274
- "$ref": "$map/item/fullName"
275
- }
276
- ]
424
+ "textContent": "Install the Jx Suite GitHub App"
425
+ },
426
+ {
427
+ "tagName": "span",
428
+ "textContent": " to grant repository access, then use Refresh below."
277
429
  }
278
430
  ]
279
431
  },
280
- "children": [
281
- {
282
- "tagName": "span",
283
- "attributes": {
284
- "part": "name"
285
- },
286
- "textContent": "${$map.item.fullName}"
432
+ "empty-none": {
433
+ "tagName": "p",
434
+ "attributes": {
435
+ "part": "empty"
287
436
  },
288
- {
289
- "tagName": "span",
290
- "attributes": {
291
- "part": "meta"
292
- },
293
- "children": [
437
+ "textContent": "Repositories the Jx Suite GitHub App can reach are listed here. Install the App, or widen its repository access, and try again."
438
+ },
439
+ "listed": {
440
+ "tagName": "jx-listbox",
441
+ "attributes": {
442
+ "part": "repo-list",
443
+ "id": "add-repo-repos"
444
+ },
445
+ "$props": {
446
+ "label": "Repositories",
447
+ "active": "${state.activeRepoId}"
448
+ },
449
+ "onselect": {
450
+ "$prototype": "Function",
451
+ "body": [
294
452
  {
295
- "tagName": "span",
296
- "attributes": {
297
- "part": "tag-slot",
298
- "role": "none"
299
- },
300
- "style": {
301
- "display": "contents"
453
+ "operator": "call",
454
+ "target": {
455
+ "$ref": "#/state/select"
302
456
  },
303
- "$switch": {
304
- "$ref": "$map/item/isJx"
305
- },
306
- "cases": {
307
- "true": {
308
- "tagName": "span",
309
- "attributes": {
310
- "part": "badge"
311
- },
312
- "textContent": "Jx"
457
+ "value": [
458
+ {
459
+ "$ref": "event#/detail"
313
460
  }
314
- }
461
+ ]
462
+ }
463
+ ],
464
+ "description": "One handler for every row, because a row's `select` bubbles; its detail is the row's value, the repository's full name."
465
+ },
466
+ "children": [
467
+ {
468
+ "$prototype": "Array",
469
+ "items": {
470
+ "$ref": "#/state/rows"
315
471
  },
316
- {
317
- "tagName": "span",
472
+ "key": {
473
+ "$ref": "$map/item/fullName"
474
+ },
475
+ "map": {
476
+ "tagName": "jx-option",
318
477
  "attributes": {
319
- "part": "private-slot",
320
- "role": "none"
478
+ "part": "repo",
479
+ "id": "${$map.item.id}",
480
+ "data-repo": "${$map.item.fullName}",
481
+ "title": "${$map.item.fullName}"
321
482
  },
322
- "style": {
323
- "display": "contents"
483
+ "$props": {
484
+ "value": {
485
+ "$ref": "$map/item/fullName"
486
+ },
487
+ "label": {
488
+ "$ref": "$map/item/fullName"
489
+ },
490
+ "description": {
491
+ "$ref": "$map/item/meta"
492
+ }
324
493
  },
325
- "$switch": {
326
- "$ref": "$map/item/isPrivate"
494
+ "ondblclick": {
495
+ "$prototype": "Function",
496
+ "body": [
497
+ {
498
+ "operator": "call",
499
+ "target": {
500
+ "$ref": "#/state/openRepo"
501
+ },
502
+ "value": [
503
+ {
504
+ "$ref": "$map/item/fullName"
505
+ }
506
+ ]
507
+ }
508
+ ]
327
509
  },
328
- "cases": {
329
- "true": {
510
+ "children": [
511
+ {
330
512
  "tagName": "span",
331
513
  "attributes": {
332
- "part": "badge"
514
+ "part": "badges",
515
+ "slot": "end"
333
516
  },
334
- "textContent": "private"
517
+ "children": [
518
+ {
519
+ "tagName": "span",
520
+ "attributes": {
521
+ "part": "tag-slot",
522
+ "role": "none"
523
+ },
524
+ "style": {
525
+ "display": "contents"
526
+ },
527
+ "$switch": {
528
+ "$ref": "$map/item/isJx"
529
+ },
530
+ "cases": {
531
+ "true": {
532
+ "tagName": "span",
533
+ "attributes": {
534
+ "part": "badge"
535
+ },
536
+ "textContent": "Jx"
537
+ }
538
+ }
539
+ },
540
+ {
541
+ "tagName": "span",
542
+ "attributes": {
543
+ "part": "private-slot",
544
+ "role": "none"
545
+ },
546
+ "style": {
547
+ "display": "contents"
548
+ },
549
+ "$switch": {
550
+ "$ref": "$map/item/isPrivate"
551
+ },
552
+ "cases": {
553
+ "true": {
554
+ "tagName": "span",
555
+ "attributes": {
556
+ "part": "badge"
557
+ },
558
+ "textContent": "private"
559
+ }
560
+ }
561
+ }
562
+ ]
335
563
  }
336
- }
337
- },
338
- {
339
- "tagName": "span",
340
- "textContent": "${$map.item.meta}"
564
+ ]
341
565
  }
342
- ]
566
+ }
567
+ ]
568
+ }
569
+ }
570
+ }
571
+ ]
572
+ },
573
+ {
574
+ "tagName": "section",
575
+ "attributes": {
576
+ "part": "detail",
577
+ "aria-label": "Project"
578
+ },
579
+ "children": [
580
+ {
581
+ "tagName": "div",
582
+ "attributes": {
583
+ "part": "detail-slot",
584
+ "role": "none"
585
+ },
586
+ "style": {
587
+ "display": "contents"
588
+ },
589
+ "$switch": {
590
+ "$ref": "#/state/hasDetail"
591
+ },
592
+ "cases": {
593
+ "false": {
594
+ "tagName": "p",
595
+ "attributes": {
596
+ "part": "empty"
343
597
  },
344
- {
345
- "tagName": "span",
346
- "attributes": {
347
- "part": "busy-slot",
348
- "role": "none"
349
- },
350
- "style": {
351
- "display": "contents"
598
+ "textContent": "Choose a repository to see the Jx projects it holds and pick the one to open."
599
+ },
600
+ "true": {
601
+ "tagName": "div",
602
+ "attributes": {
603
+ "part": "detail-body"
604
+ },
605
+ "children": [
606
+ {
607
+ "tagName": "div",
608
+ "attributes": {
609
+ "part": "detail-head"
610
+ },
611
+ "children": [
612
+ {
613
+ "tagName": "span",
614
+ "attributes": {
615
+ "part": "detail-name"
616
+ },
617
+ "textContent": "${state.detailName}"
618
+ },
619
+ {
620
+ "tagName": "span",
621
+ "attributes": {
622
+ "part": "detail-meta"
623
+ },
624
+ "textContent": "${state.detailMeta}"
625
+ }
626
+ ]
352
627
  },
353
- "$switch": {
354
- "$ref": "$map/item/importing"
628
+ {
629
+ "tagName": "jx-field",
630
+ "attributes": {
631
+ "part": "folder-row"
632
+ },
633
+ "$props": {
634
+ "span": true,
635
+ "label": "Project Folder",
636
+ "description": {
637
+ "$ref": "#/state/folderHelp"
638
+ },
639
+ "invalid": {
640
+ "$ref": "#/state/folderInvalid"
641
+ }
642
+ },
643
+ "children": [
644
+ {
645
+ "tagName": "jx-textfield",
646
+ "attributes": {
647
+ "part": "folder"
648
+ },
649
+ "$props": {
650
+ "placeholder": "Repository root",
651
+ "size": "sm",
652
+ "mono": true,
653
+ "value": {
654
+ "$ref": "#/state/folder"
655
+ },
656
+ "invalid": {
657
+ "$ref": "#/state/folderInvalid"
658
+ },
659
+ "error": {
660
+ "$ref": "#/state/folderError"
661
+ }
662
+ },
663
+ "oninput": {
664
+ "$prototype": "Function",
665
+ "body": [
666
+ {
667
+ "operator": "call",
668
+ "target": {
669
+ "$ref": "#/state/setFolder"
670
+ },
671
+ "value": [
672
+ {
673
+ "$ref": "event#/target/value"
674
+ }
675
+ ]
676
+ }
677
+ ]
678
+ },
679
+ "onkeydown": {
680
+ "$prototype": "Function",
681
+ "body": [
682
+ {
683
+ "$switch": {
684
+ "$ref": "event#/key"
685
+ },
686
+ "cases": {
687
+ "ArrowDown": [
688
+ {
689
+ "preventDefault": true
690
+ },
691
+ {
692
+ "operator": "call",
693
+ "target": {
694
+ "$ref": "#/state/moveLocation"
695
+ },
696
+ "value": [1]
697
+ }
698
+ ],
699
+ "ArrowUp": [
700
+ {
701
+ "preventDefault": true
702
+ },
703
+ {
704
+ "operator": "call",
705
+ "target": {
706
+ "$ref": "#/state/moveLocation"
707
+ },
708
+ "value": [-1]
709
+ }
710
+ ],
711
+ "Enter": [
712
+ {
713
+ "preventDefault": true
714
+ },
715
+ {
716
+ "operator": "call",
717
+ "target": {
718
+ "$ref": "#/state/confirm"
719
+ },
720
+ "value": []
721
+ }
722
+ ]
723
+ }
724
+ }
725
+ ]
726
+ }
727
+ }
728
+ ]
355
729
  },
356
- "cases": {
357
- "true": {
358
- "tagName": "span",
359
- "attributes": {
360
- "part": "busy"
730
+ {
731
+ "tagName": "div",
732
+ "attributes": {
733
+ "part": "locations-slot",
734
+ "role": "none"
735
+ },
736
+ "style": {
737
+ "display": "contents"
738
+ },
739
+ "$switch": {
740
+ "$ref": "#/state/detailState"
741
+ },
742
+ "cases": {
743
+ "loading": {
744
+ "tagName": "p",
745
+ "attributes": {
746
+ "part": "note"
747
+ },
748
+ "textContent": "Looking for project.json files…"
749
+ },
750
+ "listed": {
751
+ "tagName": "jx-listbox",
752
+ "attributes": {
753
+ "part": "location-list",
754
+ "id": "add-repo-locations"
755
+ },
756
+ "$props": {
757
+ "label": "Projects in this repository",
758
+ "active": "${state.activeLocationId}"
759
+ },
760
+ "onselect": {
761
+ "$prototype": "Function",
762
+ "body": [
763
+ {
764
+ "operator": "call",
765
+ "target": {
766
+ "$ref": "#/state/pickLocation"
767
+ },
768
+ "value": [
769
+ {
770
+ "$ref": "event#/detail"
771
+ }
772
+ ]
773
+ }
774
+ ]
775
+ },
776
+ "children": [
777
+ {
778
+ "$prototype": "Array",
779
+ "items": {
780
+ "$ref": "#/state/locations"
781
+ },
782
+ "key": {
783
+ "$ref": "$map/item/dir"
784
+ },
785
+ "map": {
786
+ "tagName": "jx-option",
787
+ "attributes": {
788
+ "part": "location",
789
+ "id": "${$map.item.id}",
790
+ "data-dir": "${$map.item.dir}",
791
+ "title": "${$map.item.path}"
792
+ },
793
+ "$props": {
794
+ "value": {
795
+ "$ref": "$map/item/dir"
796
+ },
797
+ "label": {
798
+ "$ref": "$map/item/label"
799
+ },
800
+ "description": {
801
+ "$ref": "$map/item/path"
802
+ }
803
+ },
804
+ "ondblclick": {
805
+ "$prototype": "Function",
806
+ "body": [
807
+ {
808
+ "operator": "call",
809
+ "target": {
810
+ "$ref": "#/state/confirm"
811
+ },
812
+ "value": []
813
+ }
814
+ ]
815
+ },
816
+ "children": [
817
+ {
818
+ "tagName": "jx-icon",
819
+ "attributes": {
820
+ "slot": "icon"
821
+ },
822
+ "$props": {
823
+ "name": "folder"
824
+ }
825
+ }
826
+ ]
827
+ }
828
+ }
829
+ ]
830
+ },
831
+ "empty": {
832
+ "tagName": "p",
833
+ "attributes": {
834
+ "part": "note"
835
+ },
836
+ "textContent": "No folder in this repository holds a project.json yet. Name one above if it does, or create a new project instead."
361
837
  },
362
- "textContent": "Importing…"
838
+ "unlisted": {
839
+ "tagName": "p",
840
+ "attributes": {
841
+ "part": "note"
842
+ },
843
+ "textContent": "Name the folder that holds the project's project.json, or leave the field empty to open the repository root."
844
+ },
845
+ "failed": {
846
+ "tagName": "p",
847
+ "attributes": {
848
+ "part": "note"
849
+ },
850
+ "textContent": "Studio couldn't list this repository's projects. Name the folder that holds the project.json instead."
851
+ }
363
852
  }
364
853
  }
365
- }
366
- ]
854
+ ]
855
+ }
367
856
  }
368
857
  }
369
858
  ]
370
859
  }
371
- }
860
+ ]
861
+ },
862
+ {
863
+ "tagName": "p",
864
+ "attributes": {
865
+ "part": "summary",
866
+ "aria-live": "polite"
867
+ },
868
+ "textContent": "${state.summary}"
372
869
  },
373
870
  {
374
871
  "tagName": "div",