wyreframe 0.5.0 → 0.6.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/dist/index.d.ts CHANGED
@@ -101,6 +101,21 @@ export interface SceneManager {
101
101
  }
102
102
  /** Scene change callback type */
103
103
  export type OnSceneChangeCallback = (fromScene: string | undefined, toScene: string) => void;
104
+ /** Element type for dead end clicks */
105
+ export type DeadEndElementType = 'button' | 'link';
106
+ /** Information about a clicked element with no navigation target */
107
+ export interface DeadEndClickInfo {
108
+ /** The scene ID where the click occurred */
109
+ sceneId: string;
110
+ /** The ID of the clicked element */
111
+ elementId: string;
112
+ /** The display text of the clicked element */
113
+ elementText: string;
114
+ /** The type of element that was clicked */
115
+ elementType: DeadEndElementType;
116
+ }
117
+ /** Dead end click callback type */
118
+ export type OnDeadEndClickCallback = (info: DeadEndClickInfo) => void;
104
119
  /** Render options */
105
120
  export interface RenderOptions {
106
121
  /** Theme name */
@@ -124,6 +139,12 @@ export interface RenderOptions {
124
139
  * Useful for previewing wireframes in different device contexts without modifying the source.
125
140
  */
126
141
  device?: DeviceType;
142
+ /**
143
+ * Callback fired when a button or link without a navigation target is clicked.
144
+ * Useful for handling dead-end interactions, showing modals, or custom navigation logic.
145
+ * @param info - Information about the clicked element and current scene
146
+ */
147
+ onDeadEndClick?: OnDeadEndClickCallback;
127
148
  }
128
149
  /** Render result */
129
150
  export interface RenderResult {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0EAA0E;AAC1E,yFAAyF;AACzF,yCAAyC;AACzC,OAAO,KAAK,MAAM,MAAM,0BAA0B,CAAC;AACnD,yCAAyC;AACzC,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;AACzD,yCAAyC;AACzC,OAAO,KAAK,KAAK,MAAM,+BAA+B,CAAC;AAqQvD,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAsD,CAAC;IAEvF,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAE3B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC,GAAG,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,kBAAkB,aAAa,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,SAAS,CAAsD,CAAC;IAErG,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAA4C,CAAC;IAExF,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,MAAM,CAAC,GAAQ,EAAE,OAAuB;IACtD,iFAAiF;IACjF,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;QACvD,MAAM,WAAW,GAAG,GAA6B,CAAC;QAClD,IAAI,WAAW,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,WAAW,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,8DAA8D;gBAC5D,mFAAmF,CACtF,CAAC;QACJ,CAAC;aAAM,IAAI,WAAW,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,0CAA0C;gBACxC,uFAAuF,CAC1F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,sDAAsD;YACpD,uDAAuD;YACvD,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IAED,8DAA8D;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE7C,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,YAAY,EAAE;YACZ,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI;YAC9B,eAAe,EAAE,MAAM,CAAC,YAAY,CAAC,eAAe;YACpD,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,WAAW;SAC7C;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAuB;IAC5D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEhE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,IAAI;QACJ,YAAY;QACZ,GAAG,EAAE,WAAW,CAAC,GAAG;QACpB,QAAQ,EAAE,WAAW,CAAC,QAAQ;KAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,OAAuB;IAEvB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEpD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC;AAoBD;;GAEG;AACH,SAAS,oBAAoB,CAAC,GAA2D;IACvF,mEAAmE;IACnE,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,eAAe;QAC5C,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAsG,CAAC;IAEpI,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/B,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAC1C,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC;YACH,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,oBAAoB,CAAC;SACvD,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC;SAC5C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAW,CAAC;AACvC,CAAC;AAED,eAAe;AACf,MAAM,CAAC,MAAM,OAAO,GAAW,MAAM,CAAC,OAAO,CAAC;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAW,MAAM,CAAC,cAAc,CAAC;AAE5D,iCAAiC;AACjC,eAAe;IACb,KAAK;IACL,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,MAAM;IACN,QAAQ;IACR,eAAe;IACf,GAAG;IACH,OAAO;IACP,OAAO;IACP,cAAc;CACf,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0EAA0E;AAC1E,yFAAyF;AACzF,yCAAyC;AACzC,OAAO,KAAK,MAAM,MAAM,0BAA0B,CAAC;AACnD,yCAAyC;AACzC,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;AACzD,yCAAyC;AACzC,OAAO,KAAK,KAAK,MAAM,+BAA+B,CAAC;AA6RvD,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAsD,CAAC;IAEvF,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAE3B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,MAAM,CAAC,GAAG,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM;aAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;aAC1C,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,kBAAkB,aAAa,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,SAAS,CAAsD,CAAC;IAErG,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAA4C,CAAC;IAExF,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,MAAM,CAAC,GAAQ,EAAE,OAAuB;IACtD,iFAAiF;IACjF,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,SAAS,IAAI,GAAG,EAAE,CAAC;QACvD,MAAM,WAAW,GAAG,GAA6B,CAAC;QAClD,IAAI,WAAW,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,WAAW,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,8DAA8D;gBAC5D,mFAAmF,CACtF,CAAC;QACJ,CAAC;aAAM,IAAI,WAAW,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,0CAA0C;gBACxC,uFAAuF,CAC1F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,sDAAsD;YACpD,uDAAuD;YACvD,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IAED,8DAA8D;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE7C,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,YAAY,EAAE;YACZ,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI;YAC9B,eAAe,EAAE,MAAM,CAAC,YAAY,CAAC,eAAe;YACpD,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,WAAW;SAC7C;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,OAAuB;IAC5D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEhE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,IAAI;QACJ,YAAY;QACZ,GAAG,EAAE,WAAW,CAAC,GAAG;QACpB,QAAQ,EAAE,WAAW,CAAC,QAAQ;KAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,OAAuB;IAEvB,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEpD,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;AACrC,CAAC;AAoBD;;GAEG;AACH,SAAS,oBAAoB,CAAC,GAA2D;IACvF,mEAAmE;IACnE,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,eAAe;QAC5C,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAsG,CAAC;IAEpI,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/B,QAAQ,EAAE,oBAAoB,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAC1C,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC;YACH,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,oBAAoB,CAAC;SACvD,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC;SAC5C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAW,CAAC;AACvC,CAAC;AAED,eAAe;AACf,MAAM,CAAC,MAAM,OAAO,GAAW,MAAM,CAAC,OAAO,CAAC;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAW,MAAM,CAAC,cAAc,CAAC;AAE5D,iCAAiC;AACjC,eAAe;IACb,KAAK;IACL,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,MAAM;IACN,QAAQ;IACR,eAAe;IACf,GAAG;IACH,OAAO;IACP,OAAO;IACP,cAAc;CACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wyreframe",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "ASCII wireframe + interaction DSL to HTML converter with scene transitions",
5
5
  "author": "wickedev",
6
6
  "repository": {
package/src/index.test.ts CHANGED
@@ -251,6 +251,148 @@ describe('onSceneChange callback (Issue #2)', () => {
251
251
  });
252
252
  });
253
253
 
254
+ describe('mixed text and link content (Issue #14)', () => {
255
+ // Regression test for issue #14: Text before link not rendering in mixed text-link line
256
+ // When a line contains both plain text and a link (e.g., "Don't have an account? "Sign up""),
257
+ // both parts should be rendered, not just the link.
258
+
259
+ const mixedTextLinkWireframe = `
260
+ @scene: test
261
+
262
+ +---------------------------------------+
263
+ | Don't have an account? "Sign up" |
264
+ +---------------------------------------+
265
+ `;
266
+
267
+ test('parses both text and link from mixed text-link line', () => {
268
+ const result = parse(mixedTextLinkWireframe);
269
+
270
+ expect(result.success).toBe(true);
271
+ if (result.success) {
272
+ expect(result.ast.scenes).toHaveLength(1);
273
+ const scene = result.ast.scenes[0];
274
+
275
+ // Should have elements (likely a Row containing Text and Link)
276
+ expect(scene.elements.length).toBeGreaterThan(0);
277
+
278
+ // Helper to recursively find elements
279
+ const findElements = (elements: any[], tags: string[]): any[] => {
280
+ const found: any[] = [];
281
+ for (const el of elements) {
282
+ if (tags.includes(el.TAG)) {
283
+ found.push(el);
284
+ }
285
+ if (el.children) {
286
+ found.push(...findElements(el.children, tags));
287
+ }
288
+ }
289
+ return found;
290
+ };
291
+
292
+ // Find all Text and Link elements
293
+ const textElements = findElements(scene.elements, ['Text']);
294
+ const linkElements = findElements(scene.elements, ['Link']);
295
+
296
+ // Should have at least one Text element containing "Don't have an account?"
297
+ const hasAccountText = textElements.some(
298
+ (t) => t.content && t.content.includes("Don't have an account?")
299
+ );
300
+ expect(hasAccountText).toBe(true);
301
+
302
+ // Should have the "Sign up" link
303
+ const hasSignUpLink = linkElements.some((l) => l.text === 'Sign up');
304
+ expect(hasSignUpLink).toBe(true);
305
+ }
306
+ });
307
+
308
+ test('parses link at start followed by text', () => {
309
+ const wireframe = `
310
+ @scene: test
311
+
312
+ +----------------------------+
313
+ | "Click here" for details |
314
+ +----------------------------+
315
+ `;
316
+
317
+ const result = parse(wireframe);
318
+
319
+ expect(result.success).toBe(true);
320
+ if (result.success) {
321
+ const scene = result.ast.scenes[0];
322
+
323
+ const findElements = (elements: any[], tags: string[]): any[] => {
324
+ const found: any[] = [];
325
+ for (const el of elements) {
326
+ if (tags.includes(el.TAG)) {
327
+ found.push(el);
328
+ }
329
+ if (el.children) {
330
+ found.push(...findElements(el.children, tags));
331
+ }
332
+ }
333
+ return found;
334
+ };
335
+
336
+ const textElements = findElements(scene.elements, ['Text']);
337
+ const linkElements = findElements(scene.elements, ['Link']);
338
+
339
+ // Should have "Click here" link
340
+ const hasClickHereLink = linkElements.some((l) => l.text === 'Click here');
341
+ expect(hasClickHereLink).toBe(true);
342
+
343
+ // Should have "for details" text
344
+ const hasDetailsText = textElements.some(
345
+ (t) => t.content && t.content.includes('for details')
346
+ );
347
+ expect(hasDetailsText).toBe(true);
348
+ }
349
+ });
350
+
351
+ test('parses text with link in middle', () => {
352
+ const wireframe = `
353
+ @scene: test
354
+
355
+ +------------------------------------+
356
+ | Please "click here" to continue |
357
+ +------------------------------------+
358
+ `;
359
+
360
+ const result = parse(wireframe);
361
+
362
+ expect(result.success).toBe(true);
363
+ if (result.success) {
364
+ const scene = result.ast.scenes[0];
365
+
366
+ const findElements = (elements: any[], tags: string[]): any[] => {
367
+ const found: any[] = [];
368
+ for (const el of elements) {
369
+ if (tags.includes(el.TAG)) {
370
+ found.push(el);
371
+ }
372
+ if (el.children) {
373
+ found.push(...findElements(el.children, tags));
374
+ }
375
+ }
376
+ return found;
377
+ };
378
+
379
+ const textElements = findElements(scene.elements, ['Text']);
380
+ const linkElements = findElements(scene.elements, ['Link']);
381
+
382
+ // Should have "click here" link
383
+ expect(linkElements.some((l) => l.text === 'click here')).toBe(true);
384
+
385
+ // Should have both text parts
386
+ const hasPlease = textElements.some((t) => t.content && t.content.includes('Please'));
387
+ const hasContinue = textElements.some(
388
+ (t) => t.content && t.content.includes('to continue')
389
+ );
390
+ expect(hasPlease).toBe(true);
391
+ expect(hasContinue).toBe(true);
392
+ }
393
+ });
394
+ });
395
+
254
396
  describe('device option override (Issue #11)', () => {
255
397
  const desktopWireframe = `
256
398
  @scene: test
package/src/index.ts CHANGED
@@ -151,6 +151,24 @@ export interface SceneManager {
151
151
  /** Scene change callback type */
152
152
  export type OnSceneChangeCallback = (fromScene: string | undefined, toScene: string) => void;
153
153
 
154
+ /** Element type for dead end clicks */
155
+ export type DeadEndElementType = 'button' | 'link';
156
+
157
+ /** Information about a clicked element with no navigation target */
158
+ export interface DeadEndClickInfo {
159
+ /** The scene ID where the click occurred */
160
+ sceneId: string;
161
+ /** The ID of the clicked element */
162
+ elementId: string;
163
+ /** The display text of the clicked element */
164
+ elementText: string;
165
+ /** The type of element that was clicked */
166
+ elementType: DeadEndElementType;
167
+ }
168
+
169
+ /** Dead end click callback type */
170
+ export type OnDeadEndClickCallback = (info: DeadEndClickInfo) => void;
171
+
154
172
  /** Render options */
155
173
  export interface RenderOptions {
156
174
  /** Theme name */
@@ -174,6 +192,12 @@ export interface RenderOptions {
174
192
  * Useful for previewing wireframes in different device contexts without modifying the source.
175
193
  */
176
194
  device?: DeviceType;
195
+ /**
196
+ * Callback fired when a button or link without a navigation target is clicked.
197
+ * Useful for handling dead-end interactions, showing modals, or custom navigation logic.
198
+ * @param info - Information about the clicked element and current scene
199
+ */
200
+ onDeadEndClick?: OnDeadEndClickCallback;
177
201
  }
178
202
 
179
203
  /** Render result */
@@ -12,7 +12,7 @@ function calculate(content, position, boxBounds) {
12
12
  return "Left";
13
13
  }
14
14
  let leftSpace = contentStart - boxLeft | 0;
15
- let rightSpace = boxRight - contentEnd | 0;
15
+ let rightSpace = (boxRight - contentEnd | 0) + 1 | 0;
16
16
  let leftRatio = leftSpace / boxWidth;
17
17
  let rightRatio = rightSpace / boxWidth;
18
18
  if (leftRatio < 0.2 && rightRatio > 0.3) {
@@ -43,8 +43,9 @@ let calculate = (
43
43
  Left
44
44
  } else {
45
45
  // Calculate space on each side
46
+ // Note: contentEnd is exclusive (position after last char), so we add 1 to get correct count
46
47
  let leftSpace = contentStart - boxLeft
47
- let rightSpace = boxRight - contentEnd
48
+ let rightSpace = boxRight - contentEnd + 1
48
49
 
49
50
  // Convert to ratios (0.0 to 1.0) relative to box width
50
51
  let leftRatio = Int.toFloat(leftSpace) /. Int.toFloat(boxWidth)
@@ -431,6 +431,57 @@ function splitInlineSegments(line) {
431
431
  currentText = currentText + char;
432
432
  i = i + 1 | 0;
433
433
  }
434
+ } else if (char === "\"") {
435
+ let linkStart = i;
436
+ let start$1 = i + 1 | 0;
437
+ let endPos$1;
438
+ let j$1 = start$1;
439
+ while (j$1 < len && endPos$1 === undefined) {
440
+ let currentChar = line.charAt(j$1);
441
+ if (currentChar === "\"") {
442
+ let isEscaped = j$1 > start$1 && line.charAt(j$1 - 1 | 0) === "\\";
443
+ if (!isEscaped) {
444
+ endPos$1 = j$1;
445
+ }
446
+ }
447
+ j$1 = j$1 + 1 | 0;
448
+ };
449
+ let end$1 = endPos$1;
450
+ if (end$1 !== undefined) {
451
+ let quotedContent = line.slice(start$1, end$1);
452
+ let trimmedContent = quotedContent.trim();
453
+ if (trimmedContent !== "") {
454
+ let text$1 = currentText.trim();
455
+ if (text$1 !== "") {
456
+ let leadingSpaces$1 = currentText.length - currentText.trimStart().length | 0;
457
+ segments.push({
458
+ TAG: "TextSegment",
459
+ _0: text$1,
460
+ _1: currentTextStart + leadingSpaces$1 | 0
461
+ });
462
+ }
463
+ currentText = "";
464
+ segments.push({
465
+ TAG: "LinkSegment",
466
+ _0: trimmedContent,
467
+ _1: linkStart
468
+ });
469
+ i = end$1 + 1 | 0;
470
+ currentTextStart = i;
471
+ } else {
472
+ if (currentText === "") {
473
+ currentTextStart = i;
474
+ }
475
+ currentText = currentText + char;
476
+ i = i + 1 | 0;
477
+ }
478
+ } else {
479
+ if (currentText === "") {
480
+ currentTextStart = i;
481
+ }
482
+ currentText = currentText + char;
483
+ i = i + 1 | 0;
484
+ }
434
485
  } else {
435
486
  if (currentText === "") {
436
487
  currentTextStart = i;
@@ -439,13 +490,13 @@ function splitInlineSegments(line) {
439
490
  i = i + 1 | 0;
440
491
  }
441
492
  };
442
- let text$1 = currentText.trim();
443
- if (text$1 !== "") {
444
- let leadingSpaces$1 = currentText.length - currentText.trimStart().length | 0;
493
+ let text$2 = currentText.trim();
494
+ if (text$2 !== "") {
495
+ let leadingSpaces$2 = currentText.length - currentText.trimStart().length | 0;
445
496
  segments.push({
446
497
  TAG: "TextSegment",
447
- _0: text$1,
448
- _1: currentTextStart + leadingSpaces$1 | 0
498
+ _0: text$2,
499
+ _1: currentTextStart + leadingSpaces$2 | 0
449
500
  });
450
501
  }
451
502
  return segments;
@@ -559,7 +610,7 @@ function segmentToElement(segment, basePosition, baseCol, bounds) {
559
610
  let text$2 = segment._0;
560
611
  let actualCol$2 = baseCol + segment._1 | 0;
561
612
  let position$2 = Types.Position.make(basePosition.row, actualCol$2);
562
- let id$1 = text$2.trim().toLowerCase().replace(/\\s+/g, "-").replace(/[^a-z0-9-]/g, "");
613
+ let id$1 = text$2.trim().toLowerCase().replace(/\\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
563
614
  let align$2 = AlignmentCalc.calculateWithStrategy(text$2, position$2, bounds, "RespectPosition");
564
615
  return {
565
616
  TAG: "Link",
@@ -603,23 +654,19 @@ function parseContentLine(line, lineIndex, contentStartRow, box, registry) {
603
654
  let buttonContent = "[ " + match._0 + " ]";
604
655
  return ParserRegistry.parse(registry, buttonContent, position, box.bounds);
605
656
  case "LinkSegment" :
606
- let colOffset = match._1;
607
- let actualCol$1 = (baseCol + leadingSpaces | 0) + colOffset | 0;
608
- let adjustedPosition = Types.Position.make(basePosition.row, actualCol$1);
609
- return segmentToElement({
610
- TAG: "LinkSegment",
611
- _0: match._0,
612
- _1: colOffset
613
- }, adjustedPosition, baseCol + leadingSpaces | 0, box.bounds);
657
+ let actualCol$1 = (baseCol + leadingSpaces | 0) + match._1 | 0;
658
+ let position$1 = Types.Position.make(row, actualCol$1);
659
+ let linkContent = "\"" + match._0 + "\"";
660
+ return ParserRegistry.parse(registry, linkContent, position$1, box.bounds);
614
661
  }
615
662
  }
616
- let position$1 = Types.Position.make(row, baseCol + leadingSpaces | 0);
617
- return ParserRegistry.parse(registry, trimmed, position$1, box.bounds);
663
+ let position$2 = Types.Position.make(row, baseCol + leadingSpaces | 0);
664
+ return ParserRegistry.parse(registry, trimmed, position$2, box.bounds);
618
665
  }
619
666
  let trimmedStart$1 = line.trimStart();
620
667
  let leadingSpaces$1 = line.length - trimmedStart$1.length | 0;
621
- let position$2 = Types.Position.make(row, baseCol + leadingSpaces$1 | 0);
622
- return ParserRegistry.parse(registry, trimmed, position$2, box.bounds);
668
+ let position$3 = Types.Position.make(row, baseCol + leadingSpaces$1 | 0);
669
+ return ParserRegistry.parse(registry, trimmed, position$3, box.bounds);
623
670
  }
624
671
 
625
672
  function parseBoxContent(box, gridCells, registry) {
@@ -712,6 +759,71 @@ function parseBoxContent(box, gridCells, registry) {
712
759
  return elements;
713
760
  }
714
761
 
762
+ function getBoxColumn(elem) {
763
+ if (elem.TAG === "Box") {
764
+ return elem.bounds.left;
765
+ } else {
766
+ return 0;
767
+ }
768
+ }
769
+
770
+ function groupHorizontalBoxes(elements) {
771
+ let boxes = elements.filter(el => el.TAG === "Box");
772
+ let nonBoxes = elements.filter(el => el.TAG !== "Box");
773
+ if (boxes.length <= 1) {
774
+ return elements;
775
+ }
776
+ let boxesWithRow = boxes.map(box => {
777
+ let row;
778
+ row = box.TAG === "Box" ? box.bounds.top : 0;
779
+ return [
780
+ row,
781
+ box
782
+ ];
783
+ });
784
+ let sorted = boxesWithRow.toSorted((param, param$1) => {
785
+ let rowB = param$1[0];
786
+ let rowA = param[0];
787
+ if (rowA !== rowB) {
788
+ return rowA - rowB | 0;
789
+ } else {
790
+ return getBoxColumn(param[1]) - getBoxColumn(param$1[1]) | 0;
791
+ }
792
+ });
793
+ let groups = [];
794
+ sorted.forEach(param => {
795
+ let box = param[1];
796
+ let row = param[0];
797
+ let existingGroupIdx = groups.findIndex(param => param[0] === row);
798
+ if (existingGroupIdx >= 0) {
799
+ let match = groups[existingGroupIdx];
800
+ if (match !== undefined) {
801
+ match[1].push(box);
802
+ return;
803
+ } else {
804
+ return;
805
+ }
806
+ }
807
+ groups.push([
808
+ row,
809
+ [box]
810
+ ]);
811
+ });
812
+ let groupedElements = groups.map(param => {
813
+ let groupBoxes = param[1];
814
+ if (groupBoxes.length >= 2) {
815
+ return {
816
+ TAG: "Row",
817
+ children: groupBoxes,
818
+ align: "Left"
819
+ };
820
+ } else {
821
+ return groupBoxes[0];
822
+ }
823
+ });
824
+ return nonBoxes.concat(groupedElements);
825
+ }
826
+
715
827
  function getElementRow(_elem) {
716
828
  while (true) {
717
829
  let elem = _elem;
@@ -743,7 +855,8 @@ function getElementRow(_elem) {
743
855
  function parseBoxRecursive(box, gridCells, registry) {
744
856
  let contentElements = parseBoxContent(box, gridCells, registry);
745
857
  let childBoxElements = box.children.map(childBox => parseBoxRecursive(childBox, gridCells, registry));
746
- let allChildren = contentElements.concat(childBoxElements);
858
+ let groupedChildElements = groupHorizontalBoxes(childBoxElements);
859
+ let allChildren = contentElements.concat(groupedChildElements);
747
860
  let sortedChildren = allChildren.toSorted((a, b) => {
748
861
  let rowA = getElementRow(a);
749
862
  let rowB = getElementRow(b);
@@ -858,6 +971,8 @@ export {
858
971
  segmentToElement,
859
972
  parseContentLine,
860
973
  parseBoxContent,
974
+ getBoxColumn,
975
+ groupHorizontalBoxes,
861
976
  getElementRow,
862
977
  parseBoxRecursive,
863
978
  buildScene,
@@ -727,6 +727,62 @@ let splitInlineSegments = (line: string): array<inlineSegment> => {
727
727
  i := i.contents + 1
728
728
  }
729
729
  }
730
+ } else if char === "\"" {
731
+ // Check for link pattern "..."
732
+ let linkStart = i.contents
733
+ let start = i.contents + 1
734
+ let endPos = ref(None)
735
+ let j = ref(start)
736
+ // Find matching closing quote, handling escaped quotes
737
+ while j.contents < len && endPos.contents === None {
738
+ let currentChar = line->String.charAt(j.contents)
739
+ if currentChar === "\"" {
740
+ // Check if this quote is escaped (preceded by backslash)
741
+ let isEscaped = j.contents > start && line->String.charAt(j.contents - 1) === "\\"
742
+ if !isEscaped {
743
+ endPos := Some(j.contents)
744
+ }
745
+ }
746
+ j := j.contents + 1
747
+ }
748
+
749
+ switch endPos.contents {
750
+ | Some(end) => {
751
+ let quotedContent = line->String.slice(~start, ~end)
752
+ let trimmedContent = quotedContent->String.trim
753
+
754
+ // Check if the quoted content is not empty
755
+ if trimmedContent !== "" {
756
+ // Flush any accumulated text before the link
757
+ let text = currentText.contents->String.trim
758
+ if text !== "" {
759
+ let leadingSpaces = String.length(currentText.contents) - String.length(currentText.contents->String.trimStart)
760
+ segments->Array.push(TextSegment(text, currentTextStart.contents + leadingSpaces))->ignore
761
+ }
762
+ currentText := ""
763
+
764
+ // Add the link segment
765
+ segments->Array.push(LinkSegment(trimmedContent, linkStart))->ignore
766
+ i := end + 1
767
+ currentTextStart := i.contents
768
+ } else {
769
+ // Empty quoted content, treat as regular text
770
+ if currentText.contents === "" {
771
+ currentTextStart := i.contents
772
+ }
773
+ currentText := currentText.contents ++ char
774
+ i := i.contents + 1
775
+ }
776
+ }
777
+ | None => {
778
+ // No matching closing quote, treat as regular text
779
+ if currentText.contents === "" {
780
+ currentTextStart := i.contents
781
+ }
782
+ currentText := currentText.contents ++ char
783
+ i := i.contents + 1
784
+ }
785
+ }
730
786
  } else {
731
787
  // Regular character
732
788
  if currentText.contents === "" {
@@ -965,11 +1021,14 @@ let segmentToElement = (
965
1021
  let actualCol = baseCol + colOffset
966
1022
  let position = Position.make(basePosition.row, actualCol)
967
1023
 
1024
+ // Use the same slugify logic as LinkParser for consistent ID generation
968
1025
  let id = text
969
1026
  ->String.trim
970
1027
  ->String.toLowerCase
971
1028
  ->Js.String2.replaceByRe(%re("/\\s+/g"), "-")
972
1029
  ->Js.String2.replaceByRe(%re("/[^a-z0-9-]/g"), "")
1030
+ ->Js.String2.replaceByRe(%re("/-+/g"), "-")
1031
+ ->Js.String2.replaceByRe(%re("/^-+|-+$/g"), "")
973
1032
 
974
1033
  let align = AlignmentCalc.calculateWithStrategy(
975
1034
  text,
@@ -1046,10 +1105,12 @@ let parseContentLine = (
1046
1105
  Some(registry->ParserRegistry.parse(buttonContent, position, box.bounds))
1047
1106
  }
1048
1107
  | Some(LinkSegment(text, colOffset)) => {
1049
- // For LinkSegment, we also need to account for leading spaces
1108
+ // For single LinkSegment, pass through to ParserRegistry to use LinkParser's slugify
1050
1109
  let actualCol = baseCol + leadingSpaces + colOffset
1051
- let adjustedPosition = Position.make(basePosition.row, actualCol)
1052
- Some(segmentToElement(LinkSegment(text, colOffset), adjustedPosition, baseCol + leadingSpaces, box.bounds))
1110
+ let position = Position.make(row, actualCol)
1111
+ // Reconstruct the quoted text format for the parser
1112
+ let linkContent = "\"" ++ text ++ "\""
1113
+ Some(registry->ParserRegistry.parse(linkContent, position, box.bounds))
1053
1114
  }
1054
1115
  | Some(TextSegment(_, _)) | None => {
1055
1116
  // For single text segment, use original position calculation
@@ -1180,6 +1241,100 @@ let parseBoxContent = (
1180
1241
  elements
1181
1242
  }
1182
1243
 
1244
+ /**
1245
+ * Get the column position of a Box element.
1246
+ */
1247
+ let getBoxColumn = (elem: element): int => {
1248
+ switch elem {
1249
+ | Box({bounds, _}) => bounds.left
1250
+ | _ => 0
1251
+ }
1252
+ }
1253
+
1254
+ /**
1255
+ * Group horizontally aligned box elements into Row elements.
1256
+ *
1257
+ * Boxes are considered horizontally aligned if they share the same top row.
1258
+ * Single boxes are returned as-is, while groups of 2+ are wrapped in a Row.
1259
+ *
1260
+ * @param elements - Array of elements (should be Box elements)
1261
+ * @returns Array of elements with horizontal boxes wrapped in Rows
1262
+ */
1263
+ let groupHorizontalBoxes = (elements: array<element>): array<element> => {
1264
+ // Only process Box elements - separate them from non-boxes
1265
+ let boxes = elements->Array.filter(el =>
1266
+ switch el {
1267
+ | Box(_) => true
1268
+ | _ => false
1269
+ }
1270
+ )
1271
+ let nonBoxes = elements->Array.filter(el =>
1272
+ switch el {
1273
+ | Box(_) => false
1274
+ | _ => true
1275
+ }
1276
+ )
1277
+
1278
+ // If no boxes or only one box, return as-is
1279
+ if Array.length(boxes) <= 1 {
1280
+ elements
1281
+ } else {
1282
+ // Group boxes by their top row
1283
+ let boxesWithRow = boxes->Array.map(box => {
1284
+ let row = switch box {
1285
+ | Box({bounds, _}) => bounds.top
1286
+ | _ => 0
1287
+ }
1288
+ (row, box)
1289
+ })
1290
+
1291
+ // Sort by row first, then by column within same row
1292
+ let sorted = boxesWithRow->Array.toSorted(((rowA, boxA), (rowB, boxB)) => {
1293
+ if rowA !== rowB {
1294
+ Float.fromInt(rowA - rowB)
1295
+ } else {
1296
+ Float.fromInt(getBoxColumn(boxA) - getBoxColumn(boxB))
1297
+ }
1298
+ })
1299
+
1300
+ // Group boxes by row
1301
+ let groups: array<(int, array<element>)> = []
1302
+ sorted->Array.forEach(((row, box)) => {
1303
+ // Find if there's already a group for this row
1304
+ let existingGroupIdx = groups->Array.findIndex(((groupRow, _)) => groupRow === row)
1305
+ if existingGroupIdx >= 0 {
1306
+ // Add to existing group
1307
+ switch groups->Array.get(existingGroupIdx) {
1308
+ | Some((_, groupBoxes)) => {
1309
+ groupBoxes->Array.push(box)
1310
+ }
1311
+ | None => ()
1312
+ }
1313
+ } else {
1314
+ // Create new group
1315
+ groups->Array.push((row, [box]))
1316
+ }
1317
+ })
1318
+
1319
+ // Convert groups to elements
1320
+ let groupedElements = groups->Array.map(((_, groupBoxes)) => {
1321
+ if Array.length(groupBoxes) >= 2 {
1322
+ // Wrap multiple boxes in a Row
1323
+ Row({
1324
+ children: groupBoxes,
1325
+ align: Left, // Default alignment
1326
+ })
1327
+ } else {
1328
+ // Single box, return as-is
1329
+ groupBoxes->Array.getUnsafe(0)
1330
+ }
1331
+ })
1332
+
1333
+ // Combine non-boxes with grouped elements
1334
+ Array.concat(nonBoxes, groupedElements)
1335
+ }
1336
+ }
1337
+
1183
1338
  /**
1184
1339
  * Get the row position of an element for sorting purposes.
1185
1340
  */
@@ -1238,8 +1393,11 @@ let rec parseBoxRecursive = (
1238
1393
  parseBoxRecursive(childBox, gridCells, registry)
1239
1394
  })
1240
1395
 
1241
- // Combine content elements and child boxes
1242
- let allChildren = Array.concat(contentElements, childBoxElements)
1396
+ // Group horizontally aligned child boxes into Row elements
1397
+ let groupedChildElements = groupHorizontalBoxes(childBoxElements)
1398
+
1399
+ // Combine content elements and grouped child boxes
1400
+ let allChildren = Array.concat(contentElements, groupedChildElements)
1243
1401
 
1244
1402
  // Sort elements by their row position to preserve visual order
1245
1403
  let sortedChildren = allChildren->Array.toSorted((a, b) => {