@brett_lamy/docstream 1.10.0 → 1.12.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 (63) hide show
  1. package/README.md +25 -1
  2. package/dist/docs/DocsRenderer.d.ts.map +1 -1
  3. package/dist/docs/DocsRenderer.js +2 -1
  4. package/dist/docs/DocsRenderer.js.map +1 -1
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/strudel/StepGrid.d.ts +10 -0
  10. package/dist/strudel/StepGrid.d.ts.map +1 -0
  11. package/dist/strudel/StepGrid.js +78 -0
  12. package/dist/strudel/StepGrid.js.map +1 -0
  13. package/dist/strudel/StrudelPlayer.d.ts +7 -1
  14. package/dist/strudel/StrudelPlayer.d.ts.map +1 -1
  15. package/dist/strudel/StrudelPlayer.js +37 -8
  16. package/dist/strudel/StrudelPlayer.js.map +1 -1
  17. package/dist/strudel/StrudelRack.d.ts +24 -0
  18. package/dist/strudel/StrudelRack.d.ts.map +1 -0
  19. package/dist/strudel/StrudelRack.js +123 -0
  20. package/dist/strudel/StrudelRack.js.map +1 -0
  21. package/dist/strudel/ast/edit.d.ts +41 -0
  22. package/dist/strudel/ast/edit.d.ts.map +1 -0
  23. package/dist/strudel/ast/edit.js +78 -0
  24. package/dist/strudel/ast/edit.js.map +1 -0
  25. package/dist/strudel/ast/index.d.ts +7 -0
  26. package/dist/strudel/ast/index.d.ts.map +1 -0
  27. package/dist/strudel/ast/index.js +4 -0
  28. package/dist/strudel/ast/index.js.map +1 -0
  29. package/dist/strudel/ast/mini.d.ts +86 -0
  30. package/dist/strudel/ast/mini.d.ts.map +1 -0
  31. package/dist/strudel/ast/mini.js +269 -0
  32. package/dist/strudel/ast/mini.js.map +1 -0
  33. package/dist/strudel/ast/program.d.ts +93 -0
  34. package/dist/strudel/ast/program.d.ts.map +1 -0
  35. package/dist/strudel/ast/program.js +288 -0
  36. package/dist/strudel/ast/program.js.map +1 -0
  37. package/dist/strudel/controls.d.ts +21 -0
  38. package/dist/strudel/controls.d.ts.map +1 -0
  39. package/dist/strudel/controls.js +115 -0
  40. package/dist/strudel/controls.js.map +1 -0
  41. package/dist/strudel/engine.d.ts +5 -0
  42. package/dist/strudel/engine.d.ts.map +1 -1
  43. package/dist/strudel/engine.js +14 -0
  44. package/dist/strudel/engine.js.map +1 -1
  45. package/dist/strudel/index.d.ts +9 -1
  46. package/dist/strudel/index.d.ts.map +1 -1
  47. package/dist/strudel/index.js +5 -1
  48. package/dist/strudel/index.js.map +1 -1
  49. package/dist/styles.css +598 -0
  50. package/package.json +2 -1
  51. package/src/docs/DocsRenderer.tsx +2 -1
  52. package/src/index.ts +3 -2
  53. package/src/strudel/StepGrid.tsx +130 -0
  54. package/src/strudel/StrudelPlayer.tsx +79 -8
  55. package/src/strudel/StrudelRack.tsx +322 -0
  56. package/src/strudel/ast/edit.ts +95 -0
  57. package/src/strudel/ast/index.ts +19 -0
  58. package/src/strudel/ast/mini.ts +319 -0
  59. package/src/strudel/ast/program.ts +348 -0
  60. package/src/strudel/controls.tsx +182 -0
  61. package/src/strudel/engine.ts +14 -0
  62. package/src/strudel/index.ts +17 -1
  63. package/src/styles.css +598 -0
package/dist/styles.css CHANGED
@@ -642,6 +642,604 @@
642
642
  padding: 12px 14px;
643
643
  overflow-x: auto;
644
644
  font-size: 13px;
645
+ white-space: pre;
646
+ }
647
+
648
+ /* StrudelRack: equipment generated from the code — a master strip, then one device per track. */
649
+ .docstream-strudel__revert {
650
+ align-self: flex-start;
651
+ display: inline-flex;
652
+ align-items: center;
653
+ gap: 4px;
654
+ padding: 2px 8px;
655
+ border: 1px solid var(--gb-border);
656
+ border-radius: 999px;
657
+ background: transparent;
658
+ color: var(--gb-muted-foreground);
659
+ font: inherit;
660
+ font-size: 12px;
661
+ cursor: pointer;
662
+ }
663
+
664
+ /* The rack is hardware, so it is dark in both themes: a brushed-steel 19" frame with screwed rack ears,
665
+ anodized modules with silkscreened labels, rubber knobs with LED rings, channel faders, backlit pads,
666
+ TR-style step keys and green LCDs. */
667
+ .strudel-rack {
668
+ --strudel-accent: #36d6ff;
669
+ --strudel-amber: #ff9d1c;
670
+ --strudel-red: #ff4433;
671
+ --strudel-lcd: #9dff9a;
672
+ --strudel-silk: #d9dde4;
673
+ --strudel-ear: 22px;
674
+ position: relative;
675
+ display: flex;
676
+ flex-direction: column;
677
+ gap: 10px;
678
+ padding: 12px calc(var(--strudel-ear) + 10px);
679
+ border-radius: 8px;
680
+ color: var(--strudel-silk);
681
+ font-size: 12px;
682
+ font-family: "Helvetica Neue", Arial, system-ui, sans-serif;
683
+ background:
684
+ /* rack ears: four screws */
685
+ radial-gradient(circle at calc(var(--strudel-ear) / 2) 18px, #e7e9ee 0 2px, #6b7079 2.5px 4px, transparent 4.5px),
686
+ radial-gradient(circle at calc(var(--strudel-ear) / 2) calc(100% - 18px), #e7e9ee 0 2px, #6b7079 2.5px 4px, transparent 4.5px),
687
+ radial-gradient(circle at calc(100% - var(--strudel-ear) / 2) 18px, #e7e9ee 0 2px, #6b7079 2.5px 4px, transparent 4.5px),
688
+ radial-gradient(circle at calc(100% - var(--strudel-ear) / 2) calc(100% - 18px), #e7e9ee 0 2px, #6b7079 2.5px 4px, transparent 4.5px),
689
+ /* ear plates */
690
+ linear-gradient(90deg, #9da2ab 0, #c9ccd2 9px, #8e939c var(--strudel-ear), rgb(0 0 0 / 0.5) var(--strudel-ear), transparent calc(var(--strudel-ear) + 2px)) left / calc(var(--strudel-ear) + 2px) 100% no-repeat,
691
+ linear-gradient(270deg, #9da2ab 0, #c9ccd2 9px, #8e939c var(--strudel-ear), rgb(0 0 0 / 0.5) var(--strudel-ear), transparent calc(var(--strudel-ear) + 2px)) right / calc(var(--strudel-ear) + 2px) 100% no-repeat,
692
+ /* brushed steel */
693
+ repeating-linear-gradient(0deg, rgb(255 255 255 / 0.025) 0 1px, transparent 1px 3px),
694
+ linear-gradient(180deg, #3a3d44, #24262b 30%, #1b1c20);
695
+ box-shadow:
696
+ inset 0 1px 0 rgb(255 255 255 / 0.18),
697
+ inset 0 -1px 0 rgb(0 0 0 / 0.6),
698
+ 0 1px 0 rgb(255 255 255 / 0.4),
699
+ 0 10px 24px -8px rgb(0 0 0 / 0.55);
700
+ }
701
+
702
+ .strudel-rack__master {
703
+ display: flex;
704
+ align-items: center;
705
+ gap: 14px;
706
+ padding: 10px 14px;
707
+ border-radius: 6px;
708
+ background: linear-gradient(180deg, #2c2f35, #17181c);
709
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.1), inset 0 0 0 1px rgb(0 0 0 / 0.7), 0 2px 3px rgb(0 0 0 / 0.5);
710
+ }
711
+
712
+ .strudel-rack__title {
713
+ display: flex;
714
+ flex-direction: column;
715
+ font-weight: 800;
716
+ font-size: 13px;
717
+ letter-spacing: 0.14em;
718
+ text-transform: uppercase;
719
+ color: #fff;
720
+ }
721
+
722
+ .strudel-rack__title small {
723
+ font-weight: 500;
724
+ font-size: 9px;
725
+ letter-spacing: 0.3em;
726
+ color: var(--strudel-accent);
727
+ text-shadow: 0 0 6px color-mix(in srgb, var(--strudel-accent) 60%, transparent);
728
+ }
729
+
730
+ .strudel-rack__summary {
731
+ margin-left: auto;
732
+ font-size: 9px;
733
+ letter-spacing: 0.18em;
734
+ text-transform: uppercase;
735
+ color: #8b9099;
736
+ }
737
+
738
+ .strudel-rack__error,
739
+ .strudel-device__error {
740
+ margin: 0;
741
+ color: var(--strudel-red);
742
+ font-size: 12px;
743
+ }
744
+
745
+ /* LCD: recessed green glass with a faint pixel grid. */
746
+ .strudel-lcd {
747
+ padding: 6px 10px;
748
+ border-radius: 4px;
749
+ background:
750
+ repeating-linear-gradient(0deg, rgb(0 0 0 / 0.18) 0 1px, transparent 1px 2px),
751
+ linear-gradient(180deg, #0c1a10, #10261a);
752
+ box-shadow: inset 0 2px 4px rgb(0 0 0 / 0.8), inset 0 0 0 1px rgb(0 0 0 / 0.9), 0 1px 0 rgb(255 255 255 / 0.12);
753
+ color: var(--strudel-lcd);
754
+ font-family: "SF Mono", ui-monospace, Menlo, monospace;
755
+ text-shadow: 0 0 6px color-mix(in srgb, var(--strudel-lcd) 55%, transparent);
756
+ }
757
+
758
+ .strudel-lcd--bpm {
759
+ display: inline-flex;
760
+ align-items: baseline;
761
+ gap: 4px;
762
+ min-width: 92px;
763
+ justify-content: flex-end;
764
+ font-size: 24px;
765
+ font-weight: 600;
766
+ font-variant-numeric: tabular-nums;
767
+ letter-spacing: 0.04em;
768
+ }
769
+
770
+ .strudel-lcd--bpm small {
771
+ font-size: 9px;
772
+ letter-spacing: 0.15em;
773
+ }
774
+
775
+ /* Modules: anodized faceplates with a top bevel and corner screws. */
776
+ .strudel-device {
777
+ position: relative;
778
+ border-radius: 6px;
779
+ background:
780
+ radial-gradient(circle at 8px 8px, #c4c8cf 0 1.5px, #555a62 2px 3px, transparent 3.5px),
781
+ radial-gradient(circle at calc(100% - 8px) 8px, #c4c8cf 0 1.5px, #555a62 2px 3px, transparent 3.5px),
782
+ radial-gradient(circle at 8px calc(100% - 8px), #c4c8cf 0 1.5px, #555a62 2px 3px, transparent 3.5px),
783
+ radial-gradient(circle at calc(100% - 8px) calc(100% - 8px), #c4c8cf 0 1.5px, #555a62 2px 3px, transparent 3.5px),
784
+ repeating-linear-gradient(90deg, rgb(255 255 255 / 0.018) 0 1px, transparent 1px 2px),
785
+ linear-gradient(180deg, #33363d, #212328);
786
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.14), inset 0 0 0 1px rgb(0 0 0 / 0.75), 0 3px 5px rgb(0 0 0 / 0.5);
787
+ }
788
+
789
+ .strudel-device[data-kind="drums"] { --strudel-key: var(--strudel-amber); }
790
+ .strudel-device[data-kind="melodic"],
791
+ .strudel-device[data-kind="other"] { --strudel-key: var(--strudel-accent); }
792
+
793
+ .strudel-device__head {
794
+ display: flex;
795
+ align-items: center;
796
+ gap: 8px;
797
+ padding: 7px 16px 7px 18px;
798
+ border-bottom: 1px solid rgb(0 0 0 / 0.6);
799
+ box-shadow: 0 1px 0 rgb(255 255 255 / 0.06);
800
+ color: var(--strudel-key);
801
+ }
802
+
803
+ .strudel-device__led {
804
+ width: 7px;
805
+ height: 7px;
806
+ border-radius: 999px;
807
+ background: radial-gradient(circle at 35% 35%, #d8ffd6, #2fe05a 45%, #0d6a26);
808
+ box-shadow: 0 0 6px #2fe05a, 0 0 0 1px rgb(0 0 0 / 0.7);
809
+ }
810
+
811
+ .strudel-device[data-audible="false"] .strudel-device__led {
812
+ background: radial-gradient(circle at 35% 35%, #4b524c, #1f2420);
813
+ box-shadow: 0 0 0 1px rgb(0 0 0 / 0.7);
814
+ }
815
+
816
+ .strudel-device__name {
817
+ flex: 1;
818
+ min-width: 0;
819
+ overflow: hidden;
820
+ text-overflow: ellipsis;
821
+ white-space: nowrap;
822
+ font-weight: 700;
823
+ font-size: 11px;
824
+ letter-spacing: 0.14em;
825
+ text-transform: uppercase;
826
+ color: var(--strudel-silk);
827
+ }
828
+
829
+ /* Backlit rubber pads. */
830
+ .strudel-device__toggle {
831
+ width: 26px;
832
+ height: 20px;
833
+ border: 0;
834
+ border-radius: 4px;
835
+ background: linear-gradient(180deg, #4a4e56, #2b2e34);
836
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.18), 0 2px 0 #0d0e10, 0 3px 4px rgb(0 0 0 / 0.5);
837
+ color: #9aa0a9;
838
+ font: inherit;
839
+ font-size: 10px;
840
+ font-weight: 800;
841
+ cursor: pointer;
842
+ transition: transform 60ms, box-shadow 60ms;
843
+ }
844
+
845
+ .strudel-device__toggle:active {
846
+ transform: translateY(2px);
847
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.12), 0 0 0 #0d0e10, 0 1px 2px rgb(0 0 0 / 0.5);
848
+ }
849
+
850
+ .strudel-device__toggle[data-kind="mute"][aria-pressed="true"] {
851
+ background: linear-gradient(180deg, #ffc266, var(--strudel-amber));
852
+ color: #3a1d00;
853
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.5), 0 2px 0 #7a4300, 0 0 12px color-mix(in srgb, var(--strudel-amber) 70%, transparent);
854
+ }
855
+
856
+ .strudel-device__toggle[data-kind="solo"][aria-pressed="true"] {
857
+ background: linear-gradient(180deg, #a6f0ff, var(--strudel-accent));
858
+ color: #002a36;
859
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.5), 0 2px 0 #00657d, 0 0 12px color-mix(in srgb, var(--strudel-accent) 70%, transparent);
860
+ }
861
+
862
+ .strudel-device__body {
863
+ display: flex;
864
+ gap: 14px;
865
+ padding: 12px 18px 16px;
866
+ }
867
+
868
+ .strudel-device[data-audible="false"] .strudel-device__main {
869
+ filter: saturate(0.2) brightness(0.7);
870
+ }
871
+
872
+ .strudel-device__main {
873
+ flex: 1;
874
+ min-width: 0;
875
+ display: flex;
876
+ flex-direction: column;
877
+ gap: 10px;
878
+ }
879
+
880
+ .strudel-device__selects {
881
+ display: flex;
882
+ flex-wrap: wrap;
883
+ align-items: center;
884
+ gap: 4px 16px;
885
+ align-self: flex-start;
886
+ }
887
+
888
+ .strudel-device__selects label {
889
+ display: inline-flex;
890
+ align-items: center;
891
+ gap: 6px;
892
+ font-size: 9px;
893
+ letter-spacing: 0.18em;
894
+ text-transform: uppercase;
895
+ opacity: 0.85;
896
+ }
897
+
898
+ .strudel-device__selects select {
899
+ appearance: none;
900
+ padding: 0 2px;
901
+ border: 0;
902
+ background: transparent;
903
+ color: var(--strudel-lcd);
904
+ font: inherit;
905
+ font-size: 13px;
906
+ letter-spacing: 0.04em;
907
+ text-transform: none;
908
+ text-shadow: inherit;
909
+ cursor: pointer;
910
+ }
911
+
912
+ .strudel-device__selects select:focus-visible {
913
+ outline: 1px solid var(--strudel-lcd);
914
+ border-radius: 2px;
915
+ }
916
+
917
+ .strudel-device__selects option,
918
+ .strudel-device__add option {
919
+ background: #111;
920
+ color: #eee;
921
+ }
922
+
923
+ .strudel-device__knobs {
924
+ display: flex;
925
+ flex-wrap: wrap;
926
+ align-items: flex-start;
927
+ gap: 6px 10px;
928
+ }
929
+
930
+ .strudel-device__knob {
931
+ position: relative;
932
+ }
933
+
934
+ .strudel-device__remove {
935
+ position: absolute;
936
+ top: 0;
937
+ right: 0;
938
+ display: none;
939
+ place-items: center;
940
+ width: 14px;
941
+ height: 14px;
942
+ padding: 0;
943
+ border: 0;
944
+ border-radius: 999px;
945
+ background: var(--strudel-red);
946
+ color: #fff;
947
+ cursor: pointer;
948
+ }
949
+
950
+ .strudel-device__knob:hover .strudel-device__remove,
951
+ .strudel-device__remove:focus-visible {
952
+ display: grid;
953
+ }
954
+
955
+ .strudel-device__add {
956
+ position: relative;
957
+ display: inline-grid;
958
+ place-items: center;
959
+ align-self: flex-start;
960
+ width: 40px;
961
+ height: 40px;
962
+ margin-top: 6px;
963
+ border-radius: 999px;
964
+ border: 1px dashed #5d626b;
965
+ color: #8b9099;
966
+ }
967
+
968
+ .strudel-device__add select {
969
+ position: absolute;
970
+ inset: 0;
971
+ opacity: 0;
972
+ cursor: pointer;
973
+ }
974
+
975
+ .strudel-device__add:focus-within {
976
+ outline: 2px solid var(--strudel-accent);
977
+ outline-offset: 2px;
978
+ }
979
+
980
+ /* Knob: LED ring, rubber skirt, machined cap. */
981
+ .strudel-knob {
982
+ display: flex;
983
+ flex-direction: column;
984
+ align-items: center;
985
+ width: 58px;
986
+ user-select: none;
987
+ }
988
+
989
+ .strudel-knob__dial {
990
+ width: 52px;
991
+ height: 52px;
992
+ border-radius: 999px;
993
+ cursor: ns-resize;
994
+ touch-action: none;
995
+ }
996
+
997
+ .strudel-knob[data-size="lg"] {
998
+ width: 70px;
999
+ }
1000
+
1001
+ .strudel-knob[data-size="lg"] .strudel-knob__dial {
1002
+ width: 64px;
1003
+ height: 64px;
1004
+ }
1005
+
1006
+ .strudel-knob__dial:focus-visible,
1007
+ .strudel-fader__track:focus-visible {
1008
+ outline: 2px solid var(--strudel-accent);
1009
+ outline-offset: 2px;
1010
+ }
1011
+
1012
+ .strudel-knob__dial svg { width: 100%; height: 100%; display: block; overflow: visible; }
1013
+ .strudel-knob__led { fill: #2a2d33; stroke: rgb(0 0 0 / 0.6); stroke-width: 0.5; }
1014
+ .strudel-knob__led[data-on] { fill: var(--strudel-key, var(--strudel-accent)); filter: drop-shadow(0 0 1.6px var(--strudel-key, var(--strudel-accent))); }
1015
+ .strudel-knob__shadow { fill: rgb(0 0 0 / 0.55); filter: blur(1.4px); }
1016
+ .strudel-knob__skirt { stroke: #050506; stroke-width: 0.8; }
1017
+ .strudel-knob__ridge { stroke: rgb(255 255 255 / 0.12); stroke-width: 1.2; stroke-linecap: round; }
1018
+ .strudel-knob__cap { stroke: rgb(0 0 0 / 0.5); stroke-width: 0.6; }
1019
+ .strudel-knob__brush { fill: none; stroke: rgb(255 255 255 / 0.35); stroke-width: 0.5; stroke-dasharray: 0.6 1.4; }
1020
+ .strudel-knob__pointer { stroke: #111; stroke-width: 2.4; stroke-linecap: round; }
1021
+
1022
+ .strudel-knob__value,
1023
+ .strudel-fader__value {
1024
+ font-family: "SF Mono", ui-monospace, Menlo, monospace;
1025
+ font-variant-numeric: tabular-nums;
1026
+ font-size: 10px;
1027
+ line-height: 1.5;
1028
+ color: #fff;
1029
+ }
1030
+
1031
+ .strudel-knob__label,
1032
+ .strudel-fader__label {
1033
+ font-size: 8.5px;
1034
+ font-weight: 700;
1035
+ color: var(--strudel-silk);
1036
+ text-transform: uppercase;
1037
+ letter-spacing: 0.16em;
1038
+ white-space: nowrap;
1039
+ }
1040
+
1041
+ .strudel-knob[data-disabled] .strudel-knob__dial,
1042
+ .strudel-fader[data-disabled] .strudel-fader__track {
1043
+ cursor: not-allowed;
1044
+ }
1045
+
1046
+ .strudel-knob[data-disabled] .strudel-knob__value {
1047
+ color: var(--strudel-accent);
1048
+ }
1049
+
1050
+ /* Channel fader: tick scale, slotted track, chunky ribbed cap. */
1051
+ .strudel-fader {
1052
+ display: flex;
1053
+ flex-direction: column;
1054
+ align-items: center;
1055
+ gap: 4px;
1056
+ user-select: none;
1057
+ }
1058
+
1059
+ .strudel-fader__body {
1060
+ display: flex;
1061
+ gap: 4px;
1062
+ }
1063
+
1064
+ .strudel-fader__scale {
1065
+ display: flex;
1066
+ flex-direction: column;
1067
+ justify-content: space-between;
1068
+ padding: 8px 0;
1069
+ font-size: 7px;
1070
+ line-height: 1;
1071
+ color: #8b9099;
1072
+ text-align: right;
1073
+ }
1074
+
1075
+ .strudel-fader__track {
1076
+ position: relative;
1077
+ width: 26px;
1078
+ height: 118px;
1079
+ cursor: ns-resize;
1080
+ touch-action: none;
1081
+ border-radius: 4px;
1082
+ background: repeating-linear-gradient(180deg, transparent 0 9px, rgb(255 255 255 / 0.12) 9px 10px) 0 6px / 5px calc(100% - 12px) no-repeat,
1083
+ repeating-linear-gradient(180deg, transparent 0 9px, rgb(255 255 255 / 0.12) 9px 10px) 100% 6px / 5px calc(100% - 12px) no-repeat;
1084
+ }
1085
+
1086
+ .strudel-fader__slot {
1087
+ position: absolute;
1088
+ inset: 4px calc(50% - 2.5px);
1089
+ border-radius: 3px;
1090
+ background: #050506;
1091
+ box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.9), 0 1px 0 rgb(255 255 255 / 0.1);
1092
+ }
1093
+
1094
+ .strudel-fader__cap {
1095
+ position: absolute;
1096
+ left: 1px;
1097
+ right: 1px;
1098
+ height: 22px;
1099
+ border-radius: 3px;
1100
+ background:
1101
+ linear-gradient(180deg, transparent 10px, #fff 10px 12px, transparent 12px),
1102
+ repeating-linear-gradient(180deg, rgb(0 0 0 / 0.25) 0 1px, transparent 1px 3px),
1103
+ linear-gradient(180deg, #a3a8b1, #5b6069 48%, #3e4249 52%, #7c818a);
1104
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.5), 0 3px 5px rgb(0 0 0 / 0.7), 0 0 0 1px rgb(0 0 0 / 0.6);
1105
+ }
1106
+
1107
+ /* Steps: TR-style keys that light up. */
1108
+ .strudel-steps {
1109
+ display: flex;
1110
+ flex-direction: column;
1111
+ gap: 4px;
1112
+ padding: 8px;
1113
+ border-radius: 5px;
1114
+ background: rgb(0 0 0 / 0.35);
1115
+ box-shadow: inset 0 1px 3px rgb(0 0 0 / 0.8), 0 1px 0 rgb(255 255 255 / 0.06);
1116
+ overflow-x: auto;
1117
+ }
1118
+
1119
+ .strudel-step__layers {
1120
+ display: flex;
1121
+ flex-direction: column;
1122
+ gap: 4px;
1123
+ flex: 1;
1124
+ }
1125
+
1126
+ .strudel-step__row {
1127
+ display: flex;
1128
+ gap: 4px;
1129
+ min-width: 0;
1130
+ }
1131
+
1132
+ .strudel-step {
1133
+ position: relative;
1134
+ flex: 1 1 0;
1135
+ min-width: 20px;
1136
+ display: flex;
1137
+ }
1138
+
1139
+ .strudel-step__cell,
1140
+ .strudel-step__input {
1141
+ flex: 1;
1142
+ min-width: 0;
1143
+ height: 30px;
1144
+ padding: 0 3px;
1145
+ border: 0;
1146
+ border-radius: 3px;
1147
+ font-family: "SF Mono", ui-monospace, Menlo, monospace;
1148
+ font-size: 10px;
1149
+ font-weight: 600;
1150
+ overflow: hidden;
1151
+ text-overflow: ellipsis;
1152
+ white-space: nowrap;
1153
+ }
1154
+
1155
+ .strudel-step__cell {
1156
+ position: relative;
1157
+ padding-top: 7px;
1158
+ color: #1a0d00;
1159
+ cursor: pointer;
1160
+ background: linear-gradient(180deg, color-mix(in srgb, var(--strudel-key) 70%, #fff), var(--strudel-key) 55%, color-mix(in srgb, var(--strudel-key) 75%, #000));
1161
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.55), 0 2px 0 rgb(0 0 0 / 0.75), 0 0 10px color-mix(in srgb, var(--strudel-key) 45%, transparent);
1162
+ transition: transform 50ms, box-shadow 50ms;
1163
+ }
1164
+
1165
+ /* The key's LED. */
1166
+ .strudel-step__cell::before {
1167
+ content: "";
1168
+ position: absolute;
1169
+ top: 4px;
1170
+ left: 50%;
1171
+ width: 10px;
1172
+ height: 3px;
1173
+ margin-left: -5px;
1174
+ border-radius: 2px;
1175
+ background: #fff;
1176
+ box-shadow: 0 0 5px #fff;
1177
+ }
1178
+
1179
+ .strudel-step__cell[data-rest] {
1180
+ color: transparent;
1181
+ background: linear-gradient(180deg, #4b4f57, #34373d 55%, #26282d);
1182
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.16), 0 2px 0 rgb(0 0 0 / 0.75);
1183
+ }
1184
+
1185
+ .strudel-step__cell[data-rest]::before {
1186
+ background: #1a1b1e;
1187
+ box-shadow: inset 0 0 1px #000;
1188
+ }
1189
+
1190
+ .strudel-step__cell:active {
1191
+ transform: translateY(2px);
1192
+ box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.3), 0 0 0 rgb(0 0 0 / 0.75);
1193
+ }
1194
+
1195
+ .strudel-step__cell:focus-visible,
1196
+ .strudel-step__input:focus-visible {
1197
+ outline: 2px solid #fff;
1198
+ outline-offset: 1px;
1199
+ }
1200
+
1201
+ .strudel-step__input {
1202
+ background: #0c1a10;
1203
+ color: var(--strudel-lcd);
1204
+ }
1205
+
1206
+ .strudel-step__nest {
1207
+ flex: 1;
1208
+ display: flex;
1209
+ padding: 3px;
1210
+ border-radius: 4px;
1211
+ box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.12);
1212
+ }
1213
+
1214
+ .strudel-step__nest > .strudel-step__row {
1215
+ flex: 1;
1216
+ }
1217
+
1218
+ .strudel-step__nest[data-kind="alternation"] {
1219
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--strudel-key) 45%, transparent);
1220
+ }
1221
+
1222
+ .strudel-step__nest[data-kind="alternation"] > .strudel-step__layers > .strudel-step__row {
1223
+ flex-wrap: wrap;
1224
+ }
1225
+
1226
+ .strudel-step__badge {
1227
+ position: absolute;
1228
+ top: -6px;
1229
+ right: 2px;
1230
+ padding: 0 3px;
1231
+ border-radius: 3px;
1232
+ background: #000;
1233
+ box-shadow: 0 0 0 1px rgb(255 255 255 / 0.2);
1234
+ color: var(--strudel-lcd);
1235
+ font-family: "SF Mono", ui-monospace, Menlo, monospace;
1236
+ font-size: 8px;
1237
+ line-height: 12px;
1238
+ pointer-events: none;
1239
+ }
1240
+
1241
+ .strudel-steps {
1242
+ padding-top: 10px;
645
1243
  }
646
1244
 
647
1245
  .docs-content-ref {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brett_lamy/docstream",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "GitBook-aware readonly markdown and AI stream renderer.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -140,6 +140,7 @@
140
140
  },
141
141
  "dependencies": {
142
142
  "@strudel/web": "1.3.0",
143
+ "acorn": "^8.15.0",
143
144
  "framer-motion": "^13.1.1",
144
145
  "gpu-lexer": "^0.0.2",
145
146
  "katex": "^0.18.5",
@@ -28,7 +28,8 @@ import { ReplayPreview } from "../replay/ReplayPreview"
28
28
  import { isReplayQaUrl } from "../replay/url"
29
29
  import { VideoEmbed } from "../video"
30
30
  import { StlViewer, isStlUrl } from "../stl"
31
- import { StrudelPlayer, isStrudelFile, isStrudelLanguage } from "../strudel"
31
+ import { StrudelPlayer } from "../strudel/StrudelPlayer"
32
+ import { isStrudelFile, isStrudelLanguage } from "../strudel/url"
32
33
  import { OpenApiOperation } from "../openapi/OpenApiOperation"
33
34
  import { Mermaid } from "./Mermaid"
34
35
  import { HighlightedCode } from "./HighlightedCode"
package/src/index.ts CHANGED
@@ -90,8 +90,9 @@ export { VideoEmbed } from "./video"
90
90
  export type { VideoEmbedProps } from "./video"
91
91
  export { StlViewer, isStlUrl, parseStl } from "./stl"
92
92
  export type { StlMesh, StlViewerProps } from "./stl"
93
- export { StrudelPlayer, isStrudelFile, isStrudelLanguage } from "./strudel"
94
- export type { StrudelPlayerProps } from "./strudel"
93
+ export { StrudelPlayer } from "./strudel/StrudelPlayer"
94
+ export { isStrudelFile, isStrudelLanguage } from "./strudel/url"
95
+ export type { StrudelPlayerProps } from "./strudel/StrudelPlayer"
95
96
  export { OpenApiOperation } from "./openapi/OpenApiOperation"
96
97
  export { createInlineDemoProject, createReactDemoFiles } from "./playground/project"
97
98
  export type {