@ape-egg/codecane 0.0.0-stage → 1.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/package.json CHANGED
@@ -1,6 +1,33 @@
1
1
  {
2
2
  "name": "@ape-egg/codecane",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.1.0",
4
+ "description": "Build a project up step by step: add-only step folders stacked into runnable steps, with a timeline viewer",
5
+ "type": "module",
6
+ "license": "ISC",
7
+ "author": "kkortes",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/kkortes/codecane.git",
11
+ "directory": "package"
12
+ },
13
+ "bin": {
14
+ "codecane": "core/cli.js"
15
+ },
16
+ "exports": {
17
+ ".": "./core/index.js",
18
+ "./workflow.md": "./workflow.md"
19
+ },
20
+ "files": [
21
+ "core",
22
+ "ui",
23
+ "workflow.md",
24
+ "README.md"
25
+ ],
26
+ "dependencies": {
27
+ "@ape-egg/codie": "^0.2.0",
28
+ "@ape-egg/vibe": "^4.3.17"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ }
33
+ }
@@ -0,0 +1,554 @@
1
+ :root {
2
+ --line: #2e2e33;
3
+ --dim: #8b8b94;
4
+ --accent: oklch(0.72 0.14 250);
5
+ --addition: oklch(0.76 0.13 145);
6
+ --removal: oklch(0.72 0.15 27);
7
+ --violet: oklch(0.72 0.12 300);
8
+ --yellow: oklch(0.86 0.13 90);
9
+ --text: #e8e8ec;
10
+ --slide: 0.45s cubic-bezier(0.16, 1, 0.3, 1);
11
+ color-scheme: dark;
12
+ font: 0.875rem/1.6 system-ui, sans-serif;
13
+ color: var(--text);
14
+ background: #18181b;
15
+ }
16
+
17
+ body {
18
+ display: grid;
19
+ grid-template: auto minmax(0, 1fr) / minmax(0, 1fr);
20
+ height: 100dvh;
21
+ margin: 0;
22
+ overflow: hidden;
23
+ }
24
+
25
+ header,
26
+ story-panel,
27
+ changes-list {
28
+ position: relative;
29
+ z-index: 1;
30
+ background: #18181b;
31
+ transition: translate var(--slide);
32
+ }
33
+
34
+ header[away] {
35
+ translate: 0 -100%;
36
+ }
37
+
38
+ [away] story-panel {
39
+ translate: -100%;
40
+ }
41
+
42
+ [away] changes-list {
43
+ translate: 100%;
44
+ }
45
+
46
+ [away] code-panel {
47
+ translate: 0 100%;
48
+ }
49
+
50
+ [away] failure card {
51
+ translate: -50% calc(-50% - 100dvh);
52
+ }
53
+
54
+ [fullscreen] stage {
55
+ position: fixed;
56
+ inset: 0;
57
+ }
58
+
59
+ a {
60
+ color: inherit;
61
+ }
62
+
63
+ h2 {
64
+ margin: 0;
65
+ font-size: 0.75rem;
66
+ letter-spacing: 0.06em;
67
+ text-transform: uppercase;
68
+ color: var(--dim);
69
+ }
70
+
71
+ header {
72
+ --bar: 3.8rem;
73
+ display: flex;
74
+ align-items: center;
75
+ min-height: var(--bar);
76
+ padding-left: 1.25rem;
77
+ border-bottom: 1px solid var(--line);
78
+ }
79
+
80
+ version {
81
+ margin-left: 4px;
82
+ font-size: 0.75rem;
83
+ font-weight: 400;
84
+ letter-spacing: normal;
85
+ color: var(--dim);
86
+ }
87
+
88
+ logotext-codecane {
89
+ font-size: 1.125rem;
90
+ font-weight: 700;
91
+ letter-spacing: -0.03em;
92
+ }
93
+
94
+ logotext-codecane span {
95
+ color: var(--yellow);
96
+ }
97
+
98
+ header > button {
99
+ align-self: start;
100
+ width: var(--bar);
101
+ height: var(--bar);
102
+ padding: 0;
103
+ border-radius: 0;
104
+ font-size: 1.375rem;
105
+ }
106
+
107
+ header ol {
108
+ display: grid;
109
+ flex: 1;
110
+ grid-auto-columns: max-content;
111
+ gap: 0 0.25rem;
112
+ transition: grid-template-rows 0.3s ease;
113
+ min-width: 0;
114
+ margin: 0 1.5rem;
115
+ padding: 0.75rem 0;
116
+ overflow: auto hidden;
117
+ list-style: none;
118
+ }
119
+
120
+ header[stylecheat] ol::-webkit-scrollbar {
121
+ height: var(--unit);
122
+ }
123
+
124
+ header[stylecheat] ol::-webkit-scrollbar-thumb {
125
+ background-color: var(--dim);
126
+ }
127
+
128
+ header li {
129
+ display: flex;
130
+ align-self: center;
131
+ align-items: center;
132
+ gap: 0.25rem;
133
+ max-height: 100%;
134
+ overflow: hidden;
135
+ transition: visibility 0.3s;
136
+ }
137
+
138
+ header li:not([shown]) {
139
+ visibility: hidden;
140
+ }
141
+
142
+ arrow {
143
+ color: var(--dim);
144
+ }
145
+
146
+ header a {
147
+ display: inline-flex;
148
+ align-items: center;
149
+ gap: 0.5rem;
150
+ padding: 0.25rem 0.625rem;
151
+ border-radius: 999px;
152
+ white-space: nowrap;
153
+ text-decoration: none;
154
+ color: var(--dim);
155
+ }
156
+
157
+ header li a {
158
+ --tint: 8%;
159
+ flex: 1;
160
+ }
161
+
162
+ header :is(li a, a[aria-current="page"]) {
163
+ background: color-mix(in oklch, currentColor var(--tint), transparent);
164
+ }
165
+
166
+ header li a:is(:hover, [lit], [aria-current="step"]) {
167
+ --tint: 16%;
168
+ }
169
+
170
+ header li a:not([aria-current="step"]):hover {
171
+ filter: brightness(1.4);
172
+ }
173
+
174
+ logotext-codecane a {
175
+ gap: 0;
176
+ padding-right: 0;
177
+ color: inherit;
178
+ transition: opacity 0.2s;
179
+ }
180
+
181
+ logotext-codecane a:hover {
182
+ opacity: 0.7;
183
+ }
184
+
185
+ header a:is([aria-current="step"], [aria-current="page"], [lit]) {
186
+ --tint: 16%;
187
+ color: inherit;
188
+ }
189
+
190
+ button[fork] {
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 0.25rem;
194
+ padding: 0 0.25rem;
195
+ border: 0;
196
+ font: inherit;
197
+ color: var(--violet);
198
+ background: none;
199
+ cursor: pointer;
200
+ }
201
+
202
+ split {
203
+ rotate: 90deg;
204
+ }
205
+
206
+ join {
207
+ rotate: -90deg;
208
+ }
209
+
210
+ [kind="seam"] {
211
+ --kind: var(--yellow);
212
+ }
213
+
214
+ header a[kind="seam"] {
215
+ --tint: 0%;
216
+ justify-content: center;
217
+ height: 2rem;
218
+ aspect-ratio: 1;
219
+ padding: 0;
220
+ color: var(--kind);
221
+ }
222
+
223
+ convergence {
224
+ display: grid;
225
+ gap: 0.5rem;
226
+ justify-items: start;
227
+ margin-block: 1.25rem;
228
+ padding: 0.75rem;
229
+ border-left: 2px solid var(--kind, var(--line));
230
+ background: #ffffff08;
231
+ }
232
+
233
+ convergence :is(p, ul) {
234
+ margin: 0;
235
+ }
236
+
237
+ convergence h2 {
238
+ color: var(--kind, var(--dim));
239
+ }
240
+
241
+
242
+ workspace {
243
+ --side: minmax(0, 32rem);
244
+ display: grid;
245
+ grid-template: minmax(0, 1fr) / var(--side) minmax(20rem, 1fr) var(--side);
246
+ }
247
+
248
+ story-panel,
249
+ changes-list {
250
+ overflow: auto;
251
+ }
252
+
253
+ story-panel {
254
+ display: flex;
255
+ flex-direction: column;
256
+ border-right: 1px solid var(--line);
257
+ }
258
+
259
+ story-panel [stylecheat] {
260
+ background: none;
261
+ }
262
+
263
+ panel-tabs {
264
+ padding: 1.25rem 1.25rem 0;
265
+ }
266
+
267
+ article,
268
+ file-list,
269
+ footer {
270
+ padding: 1.25rem;
271
+ }
272
+
273
+ footer {
274
+ position: sticky;
275
+ bottom: 0;
276
+ margin-top: auto;
277
+ border-top: 1px solid var(--line);
278
+ background: inherit;
279
+ }
280
+
281
+ article small {
282
+ color: var(--dim);
283
+ }
284
+
285
+ story h1 {
286
+ margin: 0.25rem 0 0.75rem;
287
+ font-size: 1.375rem;
288
+ line-height: 1.3;
289
+ }
290
+
291
+ story :is(h2, p, ul) {
292
+ margin: 0 0 0.75rem;
293
+ }
294
+
295
+ story code {
296
+ font-family: ui-monospace, monospace;
297
+ padding: 0.0625rem 0.25rem;
298
+ border-radius: 0.25rem;
299
+ background: #2a2a30;
300
+ }
301
+
302
+ story hr {
303
+ border: 0;
304
+ border-top: 1px solid var(--line);
305
+ }
306
+
307
+ story a {
308
+ color: var(--accent);
309
+ }
310
+
311
+ alternatives {
312
+ display: grid;
313
+ gap: 0.25rem;
314
+ margin-top: 1.25rem;
315
+ }
316
+
317
+ alternatives h2 {
318
+ margin-bottom: 0.25rem;
319
+ }
320
+
321
+ alternatives a {
322
+ padding: 0.375rem 0.75rem;
323
+ border-left: 2px solid var(--violet);
324
+ background: #ffffff08;
325
+ color: var(--violet);
326
+ }
327
+
328
+ alternatives a:hover {
329
+ background: #ffffff12;
330
+ }
331
+
332
+ step-links {
333
+ display: flex;
334
+ justify-content: space-between;
335
+ gap: 1rem;
336
+ color: var(--dim);
337
+ }
338
+
339
+ step-links a:hover {
340
+ color: var(--text);
341
+ }
342
+
343
+ step-links [next] {
344
+ margin-left: auto;
345
+ }
346
+
347
+ step-links a[kind="seam"] {
348
+ color: var(--kind);
349
+ }
350
+
351
+ file-list {
352
+ flex: 1;
353
+ }
354
+
355
+ file {
356
+ display: flex;
357
+ align-items: center;
358
+ gap: 0.5rem;
359
+ padding: 0.25rem 0.5rem;
360
+ border-radius: 0.25rem;
361
+ font-family: ui-monospace, monospace;
362
+ cursor: pointer;
363
+ }
364
+
365
+ folder,
366
+ dependency {
367
+ display: block;
368
+ padding: 0.25rem 0.5rem;
369
+ font-family: ui-monospace, monospace;
370
+ color: var(--dim);
371
+ }
372
+
373
+ folder ~ :is(file, dependency) {
374
+ margin-left: 1rem;
375
+ }
376
+
377
+ file span {
378
+ flex: 1;
379
+ }
380
+
381
+ file:hover,
382
+ file[aria-current="location"] {
383
+ background: #2a2a30;
384
+ }
385
+
386
+
387
+ stage {
388
+ position: relative;
389
+ display: grid;
390
+ isolation: isolate;
391
+ overflow: hidden;
392
+ background: #fff;
393
+ }
394
+
395
+ stage > :is(iframe, empty-stage) {
396
+ width: 100%;
397
+ height: 100%;
398
+ border: 0;
399
+ }
400
+
401
+ code-panel {
402
+ position: absolute;
403
+ z-index: 1;
404
+ inset: auto 0 0;
405
+ display: flex;
406
+ flex-direction: column;
407
+ height: var(--panel);
408
+ background: rgb(24 24 27 / 0.8);
409
+ transition: height var(--slide), translate var(--slide);
410
+ animation: rise var(--slide);
411
+ }
412
+
413
+ code-panel[dragging] {
414
+ transition: none;
415
+ }
416
+
417
+ code-panel[closing] {
418
+ animation: sink var(--slide) forwards;
419
+ }
420
+
421
+ @keyframes rise {
422
+ from {
423
+ bottom: calc(var(--panel) * -1);
424
+ }
425
+ }
426
+
427
+ @keyframes sink {
428
+ to {
429
+ bottom: calc(var(--panel) * -1);
430
+ }
431
+ }
432
+
433
+ grip {
434
+ height: 0.375rem;
435
+ cursor: ns-resize;
436
+ touch-action: none;
437
+ }
438
+
439
+ editor-bar {
440
+ display: flex;
441
+ align-items: center;
442
+ gap: 0.75rem;
443
+ padding: 0 0.75rem 0.5rem;
444
+ background: none;
445
+ }
446
+
447
+ editor-bar code {
448
+ margin-right: auto;
449
+ }
450
+
451
+ problem {
452
+ padding: 0.75rem 1rem;
453
+ white-space: pre-wrap;
454
+ font: 0.8125rem/1.5 ui-monospace, monospace;
455
+ color: #fff;
456
+ background: oklch(0.45 0.13 27);
457
+ }
458
+
459
+ code-panel codie[dark] {
460
+ flex: 1;
461
+ contain: size;
462
+ border-radius: 0;
463
+ --codie-bg: transparent;
464
+ }
465
+
466
+ failure {
467
+ position: absolute;
468
+ inset: 0;
469
+ background: oklch(from var(--background) l c h / 0.88);
470
+ }
471
+
472
+ failure card {
473
+ position: absolute;
474
+ top: calc((100% - var(--drawer)) * 0.45);
475
+ left: 50%;
476
+ width: min(32rem, 100% - 2rem);
477
+ translate: -50% -50%;
478
+ transition: top var(--slide), translate var(--slide);
479
+ }
480
+
481
+ [dragging] ~ failure card {
482
+ transition: translate var(--slide);
483
+ }
484
+
485
+ failure message {
486
+ white-space: pre-wrap;
487
+ font: 0.8125rem/1.5 var(--font-mono);
488
+ }
489
+
490
+ failure code {
491
+ align-self: start;
492
+ }
493
+
494
+ empty-stage {
495
+ display: grid;
496
+ place-items: center;
497
+ padding: 1rem;
498
+ color: var(--dim);
499
+ background: #18181b;
500
+ }
501
+
502
+ changes-list {
503
+ grid-column: -2;
504
+ border-left: 1px solid var(--line);
505
+ }
506
+
507
+ changes-list > h2 {
508
+ font-size: 0.875rem;
509
+ padding: 1.25rem 1.25rem 0.75rem;
510
+ }
511
+
512
+ change-diff {
513
+ display: flex;
514
+ flex-direction: column;
515
+ margin-bottom: 1rem;
516
+ counter-reset: added removed;
517
+ }
518
+
519
+ change-header {
520
+ order: -1;
521
+ position: sticky;
522
+ top: 0;
523
+ z-index: 1;
524
+ display: flex;
525
+ align-items: center;
526
+ gap: 0.5rem;
527
+ padding: 0.5rem 1.25rem;
528
+ background: #18181b;
529
+ }
530
+
531
+ change-header code {
532
+ min-width: 0;
533
+ margin-right: auto;
534
+ overflow: hidden;
535
+ direction: rtl;
536
+ text-overflow: ellipsis;
537
+ }
538
+
539
+ change-diff codie[dark] {
540
+ font-size: 0.75rem;
541
+ --codie-bg: transparent;
542
+ }
543
+
544
+ tally {
545
+ font-family: ui-monospace, monospace;
546
+ }
547
+
548
+ added {
549
+ color: var(--addition);
550
+ }
551
+
552
+ removed {
553
+ color: var(--removal);
554
+ }
@@ -0,0 +1,25 @@
1
+ <changes-list stylecheat dark>
2
+ <h2>Code changes</h2>
3
+ <!-- each changes as change (page.id + change.path) -->
4
+ <change-diff data-state="@[change.state]">
5
+ <!-- if change.binary -->
6
+ <empty-stage>Binary file</empty-stage>
7
+ <!-- else -->
8
+ <codie dark data-path="@[change.path]"></codie>
9
+ <!-- /if -->
10
+ <change-header>
11
+ <code>@[change.path]</code>
12
+ <!-- if change.state === 'added' -->
13
+ <badge bg-green text-green>Added</badge>
14
+ <!-- /if -->
15
+ <!-- if change.state === 'modified' -->
16
+ <badge bg-yellow text-yellow>Modified</badge>
17
+ <!-- /if -->
18
+ <!-- if change.state === 'removed' -->
19
+ <badge bg-red text-red>Removed</badge>
20
+ <!-- /if -->
21
+ <tally><added></added> <removed></removed></tally>
22
+ </change-header>
23
+ </change-diff>
24
+ <!-- /each -->
25
+ </changes-list>
@@ -0,0 +1,40 @@
1
+ <stage style="--drawer: @[open && !closing ? panel : 0]%">
2
+ <!-- if open -->
3
+ <code-panel style="--panel: @[panel]%" dragging="@[dragging]" closing="@[closing]" onanimationend="codecane.settle()">
4
+ <grip onpointerdown="codecane.grab(event)" onpointermove="this.hasPointerCapture(event.pointerId) && codecane.drag(event)" onlostpointercapture="codecane.snap()"></grip>
5
+ <editor-bar stylecheat dark>
6
+ <code>@[open]</code>
7
+ <!-- if editable -->
8
+ <!-- if page.files.find(file => file.path === open).forks.length > 1 -->
9
+ <button onclick="codecane.save(true)" onmouseenter="codecane.light(...$.page.files.find(file => file.path === $.open).forks)" onmouseleave="codecane.light()" secondary sm disabled="@[!(open in drafts)]">Save in @[page.files.find(file => file.path === open).forks.length] forks</button>
10
+ <!-- /if -->
11
+ <button onclick="codecane.save()" onmouseenter="codecane.light('@[page.files.find(file => file.path === open).changedBy]')" onmouseleave="codecane.light()" secondary sm disabled="@[!(open in drafts)]">Save in @[steps[page.files.find(file => file.path === open).changedBy].title]</button>
12
+ <!-- /if -->
13
+ <button onclick="codecane.run()" aria-label="Close" secondary sm><icon cross></icon></button>
14
+ </editor-bar>
15
+ <!-- if problem -->
16
+ <problem>@[problem]</problem>
17
+ <!-- /if -->
18
+ <codie dark></codie>
19
+ </code-panel>
20
+ <!-- /if -->
21
+ <!-- if src -->
22
+ <iframe src="@[src]" title="@[steps[page.id].title]"></iframe>
23
+ <!-- else -->
24
+ <empty-stage>This step has no index.html to run.</empty-stage>
25
+ <!-- /if -->
26
+ <!-- if failure -->
27
+ <failure stylecheat dark role="alert">
28
+ <card g-3>
29
+ <crow justify-between g-4>
30
+ <h4>The step threw</h4>
31
+ <badge bg-red text-red>Error</badge>
32
+ </crow>
33
+ <message>@[failure.message]</message>
34
+ <!-- if failure.at -->
35
+ <code>@[failure.at]</code>
36
+ <!-- /if -->
37
+ </card>
38
+ </failure>
39
+ <!-- /if -->
40
+ </stage>