@svelterm/core 0.1.0 → 0.23.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 (166) hide show
  1. package/CHANGELOG.md +465 -0
  2. package/README.md +42 -29
  3. package/dist/src/cli/build.d.ts +13 -0
  4. package/dist/src/cli/build.js +119 -0
  5. package/dist/src/cli/bundle.d.ts +25 -0
  6. package/dist/src/cli/bundle.js +61 -0
  7. package/dist/src/cli/dev.d.ts +10 -0
  8. package/dist/src/cli/dev.js +152 -0
  9. package/dist/src/cli/devtools.d.ts +9 -0
  10. package/dist/src/cli/devtools.js +47 -0
  11. package/dist/src/cli/init.d.ts +8 -0
  12. package/dist/src/cli/init.js +153 -0
  13. package/dist/src/cli/main.d.ts +9 -0
  14. package/dist/src/cli/main.js +52 -0
  15. package/dist/src/cli/svt-bin.d.ts +2 -0
  16. package/dist/src/cli/svt-bin.js +6 -0
  17. package/dist/src/cli/svt.d.ts +14 -0
  18. package/dist/src/cli/svt.js +76 -0
  19. package/dist/src/components/text-buffer.js +8 -5
  20. package/dist/src/css/animation-runner.d.ts +15 -6
  21. package/dist/src/css/animation-runner.js +80 -29
  22. package/dist/src/css/animation.d.ts +12 -0
  23. package/dist/src/css/animation.js +21 -0
  24. package/dist/src/css/calc.js +4 -3
  25. package/dist/src/css/color.d.ts +19 -0
  26. package/dist/src/css/color.js +371 -62
  27. package/dist/src/css/compute.d.ts +31 -4
  28. package/dist/src/css/compute.js +273 -34
  29. package/dist/src/css/defaults.d.ts +1 -1
  30. package/dist/src/css/defaults.js +9 -0
  31. package/dist/src/css/easing.d.ts +9 -0
  32. package/dist/src/css/easing.js +95 -0
  33. package/dist/src/css/incremental.d.ts +1 -1
  34. package/dist/src/css/incremental.js +2 -2
  35. package/dist/src/css/interpolate.d.ts +13 -0
  36. package/dist/src/css/interpolate.js +41 -0
  37. package/dist/src/css/parser.js +59 -3
  38. package/dist/src/css/pseudo-elements.d.ts +9 -0
  39. package/dist/src/css/pseudo-elements.js +97 -0
  40. package/dist/src/css/selector.d.ts +17 -2
  41. package/dist/src/css/selector.js +128 -13
  42. package/dist/src/css/specificity.js +17 -6
  43. package/dist/src/css/values.d.ts +6 -1
  44. package/dist/src/css/values.js +13 -6
  45. package/dist/src/debug/context.d.ts +13 -0
  46. package/dist/src/debug/context.js +11 -0
  47. package/dist/src/debug/css.d.ts +12 -0
  48. package/dist/src/debug/css.js +28 -0
  49. package/dist/src/debug/dom.d.ts +17 -0
  50. package/dist/src/debug/dom.js +92 -0
  51. package/dist/src/devtools/DevTools.compiled.js +327 -0
  52. package/dist/src/devtools/DevTools.css.js +1 -0
  53. package/dist/src/devtools/client.d.ts +36 -0
  54. package/dist/src/devtools/client.js +76 -0
  55. package/dist/src/framelog.d.ts +54 -0
  56. package/dist/src/framelog.js +99 -0
  57. package/dist/src/headless.js +12 -4
  58. package/dist/src/index.d.ts +66 -3
  59. package/dist/src/index.js +610 -81
  60. package/dist/src/input/checkable.d.ts +8 -0
  61. package/dist/src/input/checkable.js +66 -0
  62. package/dist/src/input/details.d.ts +6 -0
  63. package/dist/src/input/details.js +34 -0
  64. package/dist/src/input/focus.d.ts +6 -0
  65. package/dist/src/input/focus.js +27 -9
  66. package/dist/src/input/keyboard.d.ts +2 -2
  67. package/dist/src/input/keyboard.js +32 -5
  68. package/dist/src/input/label.d.ts +8 -0
  69. package/dist/src/input/label.js +53 -0
  70. package/dist/src/input/modal.d.ts +9 -0
  71. package/dist/src/input/modal.js +28 -0
  72. package/dist/src/input/mouse.d.ts +2 -2
  73. package/dist/src/input/mouse.js +15 -2
  74. package/dist/src/input/select.d.ts +12 -0
  75. package/dist/src/input/select.js +63 -0
  76. package/dist/src/input/selection.d.ts +48 -0
  77. package/dist/src/input/selection.js +150 -0
  78. package/dist/src/layout/engine.d.ts +2 -0
  79. package/dist/src/layout/engine.js +1092 -142
  80. package/dist/src/layout/flex.js +4 -4
  81. package/dist/src/layout/size.js +3 -2
  82. package/dist/src/layout/text.d.ts +3 -2
  83. package/dist/src/layout/text.js +96 -17
  84. package/dist/src/layout/unicode.d.ts +20 -0
  85. package/dist/src/layout/unicode.js +121 -0
  86. package/dist/src/render/animation-clock.d.ts +57 -0
  87. package/dist/src/render/animation-clock.js +221 -0
  88. package/dist/src/render/ansi-text.d.ts +26 -0
  89. package/dist/src/render/ansi-text.js +131 -0
  90. package/dist/src/render/ansi.d.ts +18 -0
  91. package/dist/src/render/ansi.js +64 -19
  92. package/dist/src/render/border.js +166 -17
  93. package/dist/src/render/buffer.d.ts +1 -0
  94. package/dist/src/render/buffer.js +5 -2
  95. package/dist/src/render/clock.d.ts +35 -0
  96. package/dist/src/render/clock.js +67 -0
  97. package/dist/src/render/color-depth.d.ts +8 -0
  98. package/dist/src/render/color-depth.js +59 -0
  99. package/dist/src/render/context.d.ts +1 -0
  100. package/dist/src/render/context.js +17 -21
  101. package/dist/src/render/cursor-emit.d.ts +18 -0
  102. package/dist/src/render/cursor-emit.js +50 -0
  103. package/dist/src/render/diff.d.ts +12 -0
  104. package/dist/src/render/diff.js +120 -0
  105. package/dist/src/render/generation.d.ts +9 -0
  106. package/dist/src/render/generation.js +14 -0
  107. package/dist/src/render/graphics-layer.d.ts +27 -0
  108. package/dist/src/render/graphics-layer.js +86 -0
  109. package/dist/src/render/image.d.ts +27 -0
  110. package/dist/src/render/image.js +113 -0
  111. package/dist/src/render/incremental-paint.d.ts +7 -3
  112. package/dist/src/render/incremental-paint.js +52 -79
  113. package/dist/src/render/inline.d.ts +59 -0
  114. package/dist/src/render/inline.js +219 -0
  115. package/dist/src/render/kitty-graphics.d.ts +24 -0
  116. package/dist/src/render/kitty-graphics.js +58 -0
  117. package/dist/src/render/paint-text.js +68 -22
  118. package/dist/src/render/paint.d.ts +8 -1
  119. package/dist/src/render/paint.js +358 -31
  120. package/dist/src/render/png.d.ts +13 -0
  121. package/dist/src/render/png.js +145 -0
  122. package/dist/src/render/scrollbar.d.ts +8 -2
  123. package/dist/src/render/scrollbar.js +71 -14
  124. package/dist/src/render/snapshot.js +3 -1
  125. package/dist/src/renderer/default.d.ts +7 -0
  126. package/dist/src/renderer/default.js +11 -0
  127. package/dist/src/renderer/index.d.ts +8 -2
  128. package/dist/src/renderer/index.js +4 -2
  129. package/dist/src/renderer/node.d.ts +109 -0
  130. package/dist/src/renderer/node.js +165 -1
  131. package/dist/src/terminal/capabilities.d.ts +33 -0
  132. package/dist/src/terminal/capabilities.js +66 -0
  133. package/dist/src/terminal/clipboard.d.ts +9 -0
  134. package/dist/src/terminal/clipboard.js +39 -0
  135. package/dist/src/terminal/io.d.ts +82 -0
  136. package/dist/src/terminal/io.js +155 -0
  137. package/dist/src/terminal/screen.d.ts +3 -10
  138. package/dist/src/terminal/screen.js +5 -28
  139. package/dist/src/terminal/stdin-router.d.ts +8 -5
  140. package/dist/src/terminal/stdin-router.js +22 -11
  141. package/dist/src/utils/node-map.d.ts +24 -0
  142. package/dist/src/utils/node-map.js +75 -0
  143. package/dist/src/vite/config.d.ts +62 -0
  144. package/dist/src/vite/config.js +191 -0
  145. package/docs/compatibility.md +67 -0
  146. package/docs/debug/devtools.md +40 -0
  147. package/docs/debug/svt.md +50 -0
  148. package/docs/distribution.md +106 -0
  149. package/docs/elements.md +120 -0
  150. package/docs/getting-started.md +177 -0
  151. package/docs/guide/css.md +187 -0
  152. package/docs/guide/input.md +143 -0
  153. package/docs/guide/layout.md +171 -0
  154. package/docs/guide/theming.md +94 -0
  155. package/docs/how-it-works.md +115 -0
  156. package/docs/inline-mode.md +77 -0
  157. package/docs/layout.md +112 -0
  158. package/docs/motion.md +91 -0
  159. package/docs/reference/README.md +65 -0
  160. package/docs/reference/css/properties/border-corner.md +82 -0
  161. package/docs/reference/css/properties/border-style.md +168 -0
  162. package/docs/reference.md +227 -0
  163. package/docs/selectors.md +80 -0
  164. package/docs/terminal-css.md +149 -0
  165. package/docs/terminals.md +83 -0
  166. package/package.json +28 -7
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: border-style
3
+ category: css/properties
4
+ summary: Controls the visual appearance of an element's border.
5
+ related:
6
+ - css/properties/border-corner
7
+ - css/properties/border-color
8
+ - css/properties/padding
9
+ - css/properties/margin
10
+ ---
11
+
12
+ # `border-style`
13
+
14
+ Selects which characters render the four edges of an element's border. Two families: **box-drawing** (thin strokes through the cell centre) and **block-character** (strips on a chosen edge of each cell). Block-character styles compose cleanly with `background-color`; box-drawing styles do not.
15
+
16
+ ## Values
17
+
18
+ | Value | Family | Composes with `background-color` |
19
+ |-------|--------|----------------------------------|
20
+ | `none` | — | n/a |
21
+ | `single` | box-drawing | no |
22
+ | `double` | box-drawing | no |
23
+ | `rounded` | box-drawing | no |
24
+ | `heavy` | box-drawing | no |
25
+ | `eighth-cell-inner` | block-character | yes |
26
+ | `eighth-cell-outer` | block-character | yes |
27
+ | `half-cell-inner` | block-character | yes |
28
+ | `half-cell-outer` | block-character | yes |
29
+ | `full-cell` | block-character | n/a (no bg shows) |
30
+
31
+ The `*-cell-inner` variants paint a strip on the **inner** edge of each border cell (facing the content). The `*-cell-outer` variants paint on the **outer** edge.
32
+
33
+ ## Box-drawing styles
34
+
35
+ `single`, `double`, `rounded`, `heavy` use Unicode box-drawing characters (`┌─┐│└┘`, `╔═╗║╚╝`, `╭─╮│╰╯`, `┏━┓┃┗┛`). The stroke runs through the centre of each cell and the surrounding cell area takes the cell's `background-color`.
36
+
37
+ ```
38
+ ┌──────────────┐
39
+ │ hello │
40
+ └──────────────┘
41
+ ```
42
+
43
+ When the element has a coloured `background-color`, the bg fills the gap around the stroke — the border looks like it's floating in a coloured frame rather than at the box edge. For coloured boxes with a visible border, prefer `*-cell-inner` instead.
44
+
45
+ ## Block-character styles
46
+
47
+ ### `eighth-cell-inner`
48
+
49
+ 1/8-cell stroke on the inner edge of each border cell. Faces the content. Corner cells are blank.
50
+
51
+ ```
52
+ ▁▁▁▁▁▁▁▁▁▁▁▁
53
+ ▕ ▏
54
+ ▕ ▏
55
+ ▔▔▔▔▔▔▔▔▔▔▔▔
56
+ ```
57
+
58
+ Combined with `background-color`, the 7/8 of each border cell that isn't the stroke takes the bg colour — the fill extends right up to the stroke.
59
+
60
+ ### `eighth-cell-outer`
61
+
62
+ Same 1/8 stroke, but on the outer edge of each border cell. Faces away from the content.
63
+
64
+ ### `half-cell-inner` / `half-cell-outer`
65
+
66
+ Same model with 1/2-cell strokes (`▄▀▐▌`). Thicker, more visible.
67
+
68
+ ### `full-cell`
69
+
70
+ Each border cell is painted entirely with `█` in the border colour. The thickest visible option; no portion of the border cell shows the cell `background-color`.
71
+
72
+ ## Corner behaviour
73
+
74
+ Block-character styles have no glyph that combines two perpendicular strokes in one cell. By default corner cells are left blank (soft-rounded look). Use [`border-corner`](border-corner.md) to make one axis own the corners instead.
75
+
76
+ | `border-corner` | Effect on `*-cell-*` styles |
77
+ |-----------------|------------------------------|
78
+ | `none` (default) | Corners blank |
79
+ | `h` | Top/bottom strokes extend through corners; sides stop one cell short |
80
+ | `v` | Left/right strokes extend through corners; top/bottom stop one cell short |
81
+
82
+ Box-drawing styles have proper corner glyphs and ignore `border-corner`.
83
+
84
+ ## Padding/margin collapse
85
+
86
+ `*-cell-*` borders have a side-asymmetric "natural gap" — the unused 7/8 (or 1/2) of each border cell. To avoid this gap visually doubling with explicit `padding`/`margin`, the unused side **collapses into** the corresponding box-model value:
87
+
88
+ - The border cell occupies 1 cell of layout regardless of facing direction.
89
+ - The "spacer" side (opposite the stroke) absorbs **1 cell** of explicit padding or margin on that side.
90
+ - `*-inner` borders absorb `margin`. `*-outer` borders absorb `padding`.
91
+
92
+ ### `eighth-cell-outer` with varying `padding`
93
+
94
+ | CSS | Visual outcome |
95
+ |-----|----------------|
96
+ | `padding: 0` | Content sits right behind the stroke (no gap) |
97
+ | `padding: 1cell` | The 1-cell border cell *is* the padding. No extra cells beyond it. |
98
+ | `padding: 2cell` | 1 extra cell of padding beyond the border cell. |
99
+
100
+ ### `eighth-cell-inner` with varying `margin`
101
+
102
+ | CSS | Visual outcome |
103
+ |-----|----------------|
104
+ | `margin: 0` | Border cell sits right against the next box (no outer gap) |
105
+ | `margin: 1cell` | The 1-cell border cell *is* the margin. No extra cells beyond it. |
106
+ | `margin: 2cell` | 1 extra cell of margin beyond the border cell. |
107
+
108
+ In short: explicit `padding`/`margin` specifies the *total* visual space on that side, with the border cell counting toward it.
109
+
110
+ ## Examples
111
+
112
+ ### Coloured box with thin border
113
+
114
+ ```css
115
+ .box {
116
+ background-color: #b00;
117
+ border-color: #0f0;
118
+ border-style: eighth-cell-inner;
119
+ padding: 0;
120
+ }
121
+ ```
122
+
123
+ ```
124
+ ▁▁▁▁▁▁▁▁▁▁▁▁
125
+ ▕ ▏
126
+ ▕ ▏
127
+ ▔▔▔▔▔▔▔▔▔▔▔▔
128
+ ```
129
+
130
+ ### Decorative thin border (no fill)
131
+
132
+ ```css
133
+ .box {
134
+ border-style: rounded;
135
+ border-color: #888;
136
+ }
137
+ ```
138
+
139
+ ```
140
+ ╭──────────────╮
141
+ │ │
142
+ │ │
143
+ ╰──────────────╯
144
+ ```
145
+
146
+ ### Block frame with corner ownership
147
+
148
+ ```css
149
+ .box {
150
+ border-style: half-cell-inner;
151
+ border-color: #fff;
152
+ border-corner: h;
153
+ }
154
+ ```
155
+
156
+ Top and bottom rows extend through the corners; sides stop one cell short.
157
+
158
+ ## Notes
159
+
160
+ - The `*-cell-*` styles use Unicode block characters (U+2580–U+259F). These are widely supported in modern terminal fonts.
161
+ - `full-cell` is essentially a thick painted frame — useful for highlighting but ignores the bg colour entirely.
162
+ - Per-side border styles are supported (e.g. `border-top: eighth-cell-inner; border-bottom: half-cell-inner`). Corners follow the `border-corner` setting regardless of mixed styles.
163
+
164
+ ## See also
165
+
166
+ - [`border-corner`](border-corner.md) — corner ownership for block-character borders
167
+ - [`border-color`](border-color.md) — colour of the border stroke
168
+ - [`padding`](padding.md), [`margin`](margin.md) — interact with the collapse rule above
@@ -0,0 +1,227 @@
1
+ # svelterm feature reference
2
+
3
+ svelterm renders Svelte components to a terminal cell grid with HTML/CSS
4
+ semantics. This is the authoritative list of what is supported, what is
5
+ approximated, and what is deliberately ignored. Standard features link to
6
+ MDN rather than re-explaining them; terminal-specific behaviour is
7
+ documented in full here.
8
+
9
+ **The rule:** any feature with a sensible meaning on a grid of character
10
+ cells works the way a browser author expects. Features with no cell-grid
11
+ meaning (pixels, fonts, sub-cell geometry) parse and are silently dropped —
12
+ never a crash. Target modes separately with
13
+ `@media (display-mode: terminal)` / `@media (display-mode: browser)`.
14
+
15
+ ---
16
+
17
+ ## Terminal-specific extensions
18
+
19
+ These do not exist in browsers and are svelterm's own surface.
20
+
21
+ ### The `cell` unit
22
+
23
+ One terminal cell — the atomic unit of layout. `width: 20cell`,
24
+ `padding: 1cell 2cell`. [`ch`](https://developer.mozilla.org/en-US/docs/Web/CSS/length#ch)
25
+ is accepted as an exact alias (1ch = 1cell), which lets stylesheets work in
26
+ both modes. All lengths round to whole cells. Unitless `0` is valid.
27
+
28
+ ### `@media (display-mode: terminal | browser)`
29
+
30
+ Reuses the standard [`display-mode`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode)
31
+ media feature with two custom values. The terminal renderer evaluates
32
+ `terminal` as true; real browsers never match either custom value, but a
33
+ `browser` block simply applies as normal CSS there. This is the documented
34
+ pattern for anything in the ignored bucket:
35
+
36
+ ```css
37
+ .card {
38
+ @media (display-mode: browser) { box-shadow: 0 2px 8px #0004; }
39
+ @media (display-mode: terminal) { border: single; }
40
+ }
41
+ ```
42
+
43
+ ### Border styles
44
+
45
+ [`border-style`](https://developer.mozilla.org/en-US/docs/Web/CSS/border-style)
46
+ takes terminal-native values drawn with box-drawing and block glyphs
47
+ (browser values like `solid`/`dashed` are ignored — use a `display-mode`
48
+ block):
49
+
50
+ | Value | Look |
51
+ |---|---|
52
+ | `single` | `┌─┐` light box drawing |
53
+ | `double` | `╔═╗` double lines |
54
+ | `rounded` | `╭─╮` rounded corners |
55
+ | `heavy` | `┏━┓` heavy lines |
56
+ | `ascii` | `+-+` plain ASCII |
57
+ | `eighth-cell-inner` / `eighth-cell-outer` | thin eighth-block edges inside/outside the cell |
58
+ | `half-cell-inner` / `half-cell-outer` | half-block edges |
59
+ | `full-cell` | full-block frame |
60
+
61
+ Borders are 1 cell thick. `border-top/right/bottom/left: true|false`
62
+ enable individual sides. `border-corner: h | v | none` picks corner
63
+ character bias. `border-color` works as standard (including
64
+ `currentColor`).
65
+
66
+ ### Colour on a terminal
67
+
68
+ Resolved colours are either ANSI palette names (`red`, `cyan`, …) or
69
+ 24-bit truecolor. CSS keywords that match the 8 basic ANSI names map to
70
+ palette entries (themeable by the user's terminal); explicit hex/`rgb()`
71
+ etc. stay exact. `transparent` means "no colour set" — the parent's
72
+ background shows through. The terminal's own dark/light scheme is detected
73
+ via OSC 11 polling (overridable through `run({ colorScheme })`) and drives
74
+ [`light-dark()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark)
75
+ and `@media (prefers-color-scheme: …)`.
76
+
77
+ ### `opacity` ≈ `dim`
78
+
79
+ There is no alpha channel. `opacity` below 1 applies the terminal's dim
80
+ attribute; the non-standard value `opacity: dim` does the same explicitly.
81
+
82
+ ### `<svt-region>`
83
+
84
+ A paint primitive that fills its layout box from a consumer-provided
85
+ cell source (used to embed full terminal emulators). It fires a `resize`
86
+ event with `{ cols, rows }` when its allocated size changes. Without an
87
+ explicit size it fills the parent box like a replaced element.
88
+
89
+ ### Focus and keys
90
+
91
+ `Tab`/`Shift+Tab` cycle focusable elements (`button`, `input`, `textarea`,
92
+ `a`, `select`, `summary`); disabled controls are skipped. The focused
93
+ element matches `:focus`. `Enter` clicks the focused element (opens `href`
94
+ on links, toggles `<details>`, cycles `<select>`); `Space` toggles
95
+ checkboxes/radios and cycles selects. Mouse clicks focus, click, and
96
+ activate the same defaults. Clicking a
97
+ [`<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label)
98
+ activates its control — wrapping or `for="id"` association both work.
99
+ `Ctrl+C` exits.
100
+
101
+ ### Interaction model for form controls
102
+
103
+ - **Checkbox** renders `[x]` / `[ ]`; **radio** renders `(•)` / `( )`
104
+ (3×1 cells). Radios group by `name` across the tree.
105
+ - **`<select>`** is a popup-less cycling control: it renders the selected
106
+ option's label plus `▾`, sized to the longest option. `ArrowUp`/
107
+ `ArrowDown` move the selection (wrapping); `Space`/`Enter`/click advance.
108
+ There is no dropdown popup — it has no good cell-grid answer.
109
+ - **`<progress>`/`<meter>`** render as 20×1 block-glyph bars (`█` fill
110
+ with eighth-block partials, `░` track), stylable via `color`/
111
+ `background`, sized via `width`/`height`.
112
+
113
+ ### Events
114
+
115
+ W3C-style capture/bubble dispatch on the component tree: `click`,
116
+ `keydown`, `input`, `change`, `paste`, `toggle` (details), `resize`
117
+ (svt-region), plus mouse events with cell coordinates. Event payloads ride
118
+ on `event.data` (e.g. `{ value, cursor }`, `{ checked }`).
119
+
120
+ ---
121
+
122
+ ## HTML elements
123
+
124
+ Standard semantics unless noted. Anything unlisted renders as a plain
125
+ block/inline box per its display default.
126
+
127
+ | Element | Notes | Reference |
128
+ |---|---|---|
129
+ | headings, `p`, `div`, `span`, lists, `blockquote`, `pre`, `code`, `hr` | UA-styled like a browser (margins in cells, `hr` as `─` rule, list markers) | [HTML elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) |
130
+ | `strong`/`b`, `em`/`i`, `u`, `s`/`del`, `mark`, `kbd`, `abbr`, `samp`, `var` | text attributes (bold/italic/underline/strikethrough/colour) | — |
131
+ | `a` | underlined, focusable; Enter/click opens `href` in the local browser | [`<a>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a) |
132
+ | `table` and friends | full table layout: colspan/rowspan, header/footer groups, caption, `colgroup`/`col` width hints, collapse/separate borders, `empty-cells` | [`<table>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table) |
133
+ | `input` (text) | single-line editor with cursor, `value`, `input` events | [`<input>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input) |
134
+ | `input type="checkbox" / "radio"` | glyph toggles; `checked` attribute/property; `change`+`input` events | [checkbox](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox), [radio](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio) |
135
+ | `textarea` | multi-line editing | [`<textarea>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea) |
136
+ | `button` | focusable, centred text, `click` on Enter/click | [`<button>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button) |
137
+ | `select`/`option`/`optgroup` | cycling control (see above); `change`+`input` with the option value | [`<select>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) |
138
+ | `progress`, `meter` | block-glyph bars; `value`/`max` (+`min` for meter); no-value progress renders track only | [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress), [`<meter>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter) |
139
+ | `details`/`summary` | ▶/▼ disclosure, `open` attribute, `toggle` event, focusable summary | [`<details>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details) |
140
+ | `img` | half-block pixels (▀) from PNG file paths / `data:image/png` URIs; real pixels via the kitty graphics protocol where supported; sized by CSS `width`/`height` | [`<img>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img) |
141
+ | `video`, `canvas`, `iframe` | not rendered | — |
142
+
143
+ ## CSS selectors
144
+
145
+ All standard matching semantics. Reference: [MDN selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors).
146
+
147
+ - Type, `.class`, `#id`, `*`, selector lists (`a, b`)
148
+ - Combinators: descendant, `>`, `+`, `~`
149
+ - Attributes: `[a]`, `[a=v]`, `[a^=v]`, `[a$=v]`, `[a*=v]`, `[a~=v]`, `[a|=v]` (quoted or unquoted values)
150
+ - Pseudo-classes: `:root`, `:focus`, `:hover` (mouse), `:first-child`,
151
+ `:last-child`, `:only-child`, `:empty`, `:first-of-type`,
152
+ `:last-of-type`, `:only-of-type`, `:nth-child()`, `:nth-last-child()`,
153
+ `:nth-of-type()`, `:nth-last-of-type()` (full An+B), `:not()`, `:is()`,
154
+ `:where()`, `:checked`, `:disabled`, `:enabled`
155
+ - Pseudo-elements: `::before`, `::after` (single-colon legacy accepted)
156
+ with `content:` strings, `attr(x)`, space-separated concatenation, and
157
+ `none`/`""`. `counter()` is not supported. Pseudo boxes are inline and
158
+ invisible to `:empty`/`:nth-*`. Known gap: pseudo-elements don't render
159
+ inside table-internal boxes.
160
+ - Specificity, source order, and inline-`style` precedence follow the
161
+ [cascade](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Cascade).
162
+
163
+ ## CSS properties
164
+
165
+ Grouped; all standard behaviour (per MDN) except the noted grid
166
+ adaptations. Lengths are cells (`cell`/`ch`, `%`, or `calc()`).
167
+
168
+ | Group | Properties |
169
+ |---|---|
170
+ | [Colour & text](https://developer.mozilla.org/en-US/docs/Web/CSS/color) | `color`, `background`/`background-color`, `font-weight` (≥700 = bold), `font-style` (italic), `text-decoration` (underline/line-through), `text-transform`, `text-align`, `text-overflow` (`ellipsis`, plus non-standard `ellipsis-middle`), `white-space` (`normal`/`nowrap`/`pre`), `opacity` (≈dim), `visibility` |
171
+ | [Box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_box_model) | `width`, `height`, `min/max-width`, `min/max-height`, `padding(-*)`, `margin(-*)` (incl. `auto` centring and margin collapse), `box-sizing`, `overflow` (`hidden`/`scroll`/`auto` with real scrolling + fading scrollbars) |
172
+ | [Display & flow](https://developer.mozilla.org/en-US/docs/Web/CSS/display) | `display: block, inline, inline-block, flex, grid, none, contents`, all table display types |
173
+ | [Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexible_box_layout) | `flex-direction` (all four), `flex-wrap`, `flex`/`flex-grow`/`flex-shrink`/`flex-basis`, `gap`, `justify-content` (incl. `space-*`), `align-items`, `align-self`, `order` |
174
+ | [Grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout) | `grid-template-columns/rows` (`cell`/`ch`/`%`/`fr`, `repeat()`, `minmax()`), `grid-template-areas` + `grid-area` (named and numeric), `grid-column`, `grid-row` (start / start‑end / `span n`), `gap`. Auto-flow is row-based; `grid-auto-flow: column` is not implemented. Fractional `minmax()` minimums are enforced without redistribution |
175
+ | [Positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/position) | `position: static/relative/absolute/fixed/sticky` with `top/right/bottom/left`, `z-index`. Relative offsets shift visually without moving flow; sticky is top-edge only inside scroll containers (no push-out at the containing block end) |
176
+ | [Tables](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_table) | `border-collapse`, `border-spacing`, `caption-side`, `table-layout`, `empty-cells`, `vertical-align` (`baseline` ≈ `top`) |
177
+ | Borders | `border`/`border-style`/`border-color`/`border-corner` + per-side toggles (terminal values above) |
178
+ | [Animation](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations) | `animation` shorthand, `animation-name/-duration/-iteration-count` (incl. `infinite`)/`-timing-function`, `@keyframes` (from/to/percentages, values resolve `var()`/`light-dark()`) |
179
+ | [Transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transitions) | `transition` shorthand, `transition-property` (list or `all`), `transition-duration`, `transition-timing-function` |
180
+ | [Easing](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function) | `linear`, `ease` (default), `ease-in`, `ease-out`, `ease-in-out`, `cubic-bezier()`, `steps()`, `step-start`, `step-end` |
181
+
182
+ ### Animation & transition semantics on the grid
183
+
184
+ Colours interpolate in RGB at ~30fps; single cell/ch lengths interpolate
185
+ to whole cells (movement steps cell by cell); every other supported
186
+ property applies discretely, switching at the segment midpoint (the CSS
187
+ rule for non-interpolable values). Layout-affecting animations re-flow
188
+ each frame. Easing applies per keyframe segment; non-interpolable values
189
+ switch when eased progress crosses the midpoint. Deviations: one duration
190
+ and one timing function for all listed transition properties, interrupted
191
+ transitions restart from the previous target value, keyframe
192
+ `var()`/`light-dark()` resolves once at animation start, and per-keyframe
193
+ `animation-timing-function` overrides are ignored.
194
+
195
+ ## Values, functions and at-rules
196
+
197
+ - Units: `cell`/`ch`, `%`, unitless `0`, `fr` (grid). Everything
198
+ pixel-derived is dropped (see below).
199
+ - [`var()`](https://developer.mozilla.org/en-US/docs/Web/CSS/var) custom
200
+ properties with inheritance and fallbacks.
201
+ - [`calc()`](https://developer.mozilla.org/en-US/docs/Web/CSS/calc),
202
+ `min()`, `max()`, `clamp()` over cells and `%`.
203
+ - Colours: hex (3/6/8 digit), `rgb()`/`rgba()`, `hsl()`/`hsla()`, `hwb()`,
204
+ `lab()`, `lch()`, `oklab()`, `oklch()` (legacy and modern syntax), all
205
+ 148 named colours, `transparent`, `currentColor`,
206
+ [`light-dark()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark).
207
+ Alpha composites at paint time (blends over the cell beneath), and
208
+ numeric `opacity` acts as a blend factor.
209
+ - Keywords: `inherit`, `initial`, `unset`.
210
+ - At-rules: [`@media`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media)
211
+ (`prefers-color-scheme`, `display-mode`, `min/max-width`, `min/max-height`
212
+ — in cells), [`@container`](https://developer.mozilla.org/en-US/docs/Web/CSS/@container)
213
+ (size queries against the nearest laid-out ancestor),
214
+ [`@supports`](https://developer.mozilla.org/en-US/docs/Web/CSS/@supports)
215
+ (property-name checks), `@keyframes`. Nested rules inside declarations
216
+ (`& {}`-less media nesting) are supported.
217
+
218
+ ## Ignored (no cell-grid meaning)
219
+
220
+ These parse and are dropped silently. Use `@media (display-mode: browser)`
221
+ for the browser-side styling and a terminal-native equivalent if needed.
222
+
223
+ `px`/`em`/`rem`/`ex`/`vw`/`vh` lengths · `font-size`, `font-family`,
224
+ `line-height`, `letter-spacing`, `word-spacing` · `border-radius` (use
225
+ `border: rounded`), `box-shadow`, `outline`, `filter`, `backdrop-filter` ·
226
+ `transform` and friends · `background-image`, gradients · `float` ·
227
+ `@font-face`, `@page`.
@@ -0,0 +1,80 @@
1
+ # Selectors and the cascade
2
+
3
+ The selector engine implements standard
4
+ [CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)
5
+ with spec matching semantics, plus `::before`/`::after` generated
6
+ content. Specificity, source order, and inline-`style` precedence follow
7
+ the [cascade](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Cascade);
8
+ `inherit`, `initial`, and `unset` work.
9
+
10
+ ## Simple selectors and combinators
11
+
12
+ - Type (`div`), class (`.card`), id (`#main`), universal (`*`), and
13
+ selector lists (`h1, h2`).
14
+ - Combinators: descendant (`nav a`), child (`ul > li`), adjacent sibling
15
+ (`h2 + p`), general sibling (`h2 ~ p`).
16
+
17
+ ## Attribute selectors
18
+
19
+ All operators, quoted or unquoted:
20
+
21
+ | Form | Matches |
22
+ |---|---|
23
+ | `[disabled]` | attribute present |
24
+ | `[type="text"]` | exact value |
25
+ | `[href^="https"]` | prefix |
26
+ | `[href$=".pdf"]` | suffix |
27
+ | `[href*="docs"]` | substring |
28
+ | `[data-tags~="beta"]` | whitespace-separated word |
29
+ | `[lang\|="en"]` | exact or dash-prefixed (`en-GB`) |
30
+
31
+ One renderer nuance: Svelte stringifies attribute values, so
32
+ `disabled={false}` arrives as the string `"false"` — svelterm's boolean
33
+ attribute handling (`:disabled`, `[open]` behaviours, focus skipping)
34
+ treats `"false"` as off.
35
+
36
+ ## Pseudo-classes
37
+
38
+ - **Structural:** `:root`, `:first-child`, `:last-child`, `:only-child`,
39
+ `:empty` (comments and empty text ignored, as in browsers),
40
+ `:first-of-type`, `:last-of-type`, `:only-of-type`, and the full An+B
41
+ family — `:nth-child()`, `:nth-last-child()`, `:nth-of-type()`,
42
+ `:nth-last-of-type()` (`odd`, `even`, `3`, `2n+1`, `-n+3`…).
43
+ - **State:** `:focus` (keyboard/mouse focus), `:hover` (mouse),
44
+ `:checked`, `:disabled`, `:enabled` (form controls only, as in
45
+ browsers).
46
+ - **Logical:** `:not()`, `:is()`, `:where()` (zero specificity), each
47
+ taking selector lists.
48
+
49
+ ```css
50
+ tr:nth-child(even) { background: #16181d; }
51
+ input:checked { color: green; }
52
+ button:disabled { opacity: dim; }
53
+ details[open] > summary { color: cyan; }
54
+ ```
55
+
56
+ ## Pseudo-elements: `::before` / `::after`
57
+
58
+ Generated content renders as an inline box at the start/end of the
59
+ element (legacy single-colon syntax accepted):
60
+
61
+ ```css
62
+ a[href$=".pdf"]::after { content: " [pdf]"; color: red; }
63
+ .badge::before { content: attr(data-count) " "; font-weight: bold; }
64
+ ```
65
+
66
+ `content:` supports quoted strings, `attr(x)` against the host element,
67
+ space-separated concatenation, and `none`/`""` (no box). `counter()` is
68
+ not supported. Pseudo boxes are invisible to `:empty` and `:nth-*`, and
69
+ style like inline elements (they inherit the host's visual attributes
70
+ unless the pseudo rule overrides them).
71
+
72
+ Known gap: pseudo-elements don't render inside table-internal layout
73
+ boxes.
74
+
75
+ ## What re-resolves when
76
+
77
+ Selector matching is live: any attribute change (including inline
78
+ `style`, `checked`, `open`, `data-*`) re-resolves the element and its
79
+ descendants, so state-dependent rules like `details[open] > *` or
80
+ `[data-status="error"]` update as your component mutates.
@@ -0,0 +1,149 @@
1
+ # Terminal CSS
2
+
3
+ The terminal-specific surface: what svelterm adds to CSS, and how familiar
4
+ properties map onto a character grid. Everything here is invalid or inert
5
+ in browsers by design — the same stylesheet runs in both modes.
6
+
7
+ ## The `cell` unit
8
+
9
+ One terminal cell is the atomic unit of layout:
10
+
11
+ ```css
12
+ .sidebar { width: 24cell; padding: 1cell 2cell; }
13
+ ```
14
+
15
+ - [`ch`](https://developer.mozilla.org/en-US/docs/Web/CSS/length#ch) is an
16
+ exact alias (`1ch` = `1cell`). Prefer `ch` in dual-target stylesheets —
17
+ browsers understand it too, and on a monospace grid it means the same
18
+ thing.
19
+ - All lengths round to whole cells; `4.6cell` is 5.
20
+ - Unitless `0` is valid, as in CSS. `%` is relative to the containing
21
+ block's cells. `fr` works in grid templates.
22
+ - Pixel-derived units (`px`, `em`, `rem`, `vw`, `vh`…) parse and are
23
+ dropped — see [compatibility](./compatibility.md).
24
+
25
+ ## Targeting one mode
26
+
27
+ svelterm evaluates `@media (display-mode: terminal)` as true; a
28
+ `display-mode: browser` block is ignored by the terminal and applies in
29
+ real browsers as plain CSS:
30
+
31
+ ```css
32
+ .card {
33
+ @media (display-mode: browser) { box-shadow: 0 2px 8px #0004; }
34
+ @media (display-mode: terminal) { border: single; }
35
+ }
36
+ ```
37
+
38
+ This is the documented pattern for everything svelterm deliberately
39
+ ignores (shadows, radii, fonts, transforms).
40
+
41
+ ## Borders
42
+
43
+ [`border-style`](https://developer.mozilla.org/en-US/docs/Web/CSS/border-style)
44
+ takes terminal-native values drawn with box-drawing and block glyphs.
45
+ Browser values (`solid`, `dashed`…) are ignored.
46
+
47
+ | Value | Look |
48
+ |---|---|
49
+ | `single` | `┌─┐` light box drawing |
50
+ | `double` | `╔═╗` double lines |
51
+ | `rounded` | `╭─╮` rounded corners |
52
+ | `heavy` | `┏━┓` heavy lines |
53
+ | `ascii` | `+-+` plain ASCII |
54
+ | `eighth-cell-inner` / `-outer` | thin eighth-block edges inside/outside the cell |
55
+ | `half-cell-inner` / `-outer` | half-block edges |
56
+ | `full-cell` | full-block frame |
57
+
58
+ - Borders are exactly one cell thick and consume layout space.
59
+ - Individual sides: `border-top: true` / `false` (setting one side first
60
+ disables the others).
61
+ - `border-corner: h | v | none` biases which line wins at corners.
62
+ - `border-color` is standard, including `currentColor`.
63
+ - Tables support `border-collapse: collapse` with shared grid lines.
64
+
65
+ ```css
66
+ .panel { border: rounded; border-color: cyan; }
67
+ .rule { border-top: true; border-style: single; } /* horizontal rule */
68
+ ```
69
+
70
+ ## Colour
71
+
72
+ Resolved colours are ANSI palette names or 24-bit truecolor:
73
+
74
+ - The 8 basic CSS keywords (`red`, `cyan`, …) map to ANSI palette names —
75
+ the user's terminal theme can restyle them.
76
+ - Hex, `rgb()`, `hsl()`, `hwb()`, `lab()`, `lch()`, `oklab()`, `oklch()`
77
+ and the 148 named colours resolve to exact truecolor.
78
+ - `transparent` means "no colour set": the parent's background shows
79
+ through. There is no alpha blending.
80
+ - `currentColor` works wherever a colour is valid.
81
+
82
+ ### Dark/light schemes
83
+
84
+ The terminal's own scheme is detected by polling OSC 11 (override with
85
+ `run({ colorScheme })` or `setColorScheme()`). It drives both:
86
+
87
+ ```css
88
+ :root { color-scheme: light dark; }
89
+ .hint { color: light-dark(#64748b, #94a3b8); }
90
+ @media (prefers-color-scheme: dark) { .logo { color: cyan; } }
91
+ ```
92
+
93
+ [`light-dark()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark)
94
+ is usually the shortest way to theme a component for both schemes.
95
+
96
+ ## Alpha and opacity
97
+
98
+ Terminals have no alpha layer, so svelterm composites at paint time:
99
+ `rgba()`, `#rrggbbaa` and slash-alpha colours blend over whatever the
100
+ cell already holds, and numeric `opacity` folds into the element's
101
+ colours as a blend factor. Blending over ANSI colour names uses their
102
+ nominal xterm values; blending over the terminal's *default* background
103
+ assumes black — set an explicit background on an ancestor when
104
+ compositing in light themes.
105
+
106
+ ```css
107
+ .overlay { background: rgb(0 0 0 / 0.4); } /* darkens what's beneath */
108
+ .muted { opacity: 0.6; } /* blends toward the bg */
109
+ ```
110
+
111
+ The non-standard `opacity: dim` applies the terminal's *dim* attribute
112
+ instead of blending. Animating `opacity` switches discretely — animate a
113
+ colour toward the background for a smooth fade.
114
+
115
+ ## Text attributes
116
+
117
+ `font-weight: bold`, `font-style: italic`, `text-decoration: underline`
118
+ and `line-through` map to terminal attributes. `text-transform`,
119
+ `text-align`, `white-space` (`normal`/`nowrap`/`pre`), `word-break`
120
+ (`normal`/`break-all`), and `text-overflow: ellipsis` (plus non-standard
121
+ `ellipsis-middle`, which keeps both ends of long paths) behave as
122
+ standard. Font *choice* and *size* are the terminal emulator's business —
123
+ `font-family`, `font-size`, `line-height` are ignored.
124
+
125
+ Text is measured in **grapheme clusters and cell widths**: CJK and
126
+ fullwidth characters occupy two cells, emoji (including ZWJ sequences)
127
+ two, combining marks zero — so `1ch`-based layouts, wrapping, truncation
128
+ and borders stay aligned with non-Latin content. Caveat: emoji width
129
+ ultimately depends on the terminal's font; svelterm follows the modern
130
+ two-cell convention.
131
+
132
+ ## `<svt-ansi>`
133
+
134
+ Raw ANSI passthrough for pre-styled output — `git diff`, `ls --color`,
135
+ build logs. Its text content renders with its own SGR styling (16/256/
136
+ truecolor, bold, underline, …); non-SGR escape sequences are stripped.
137
+ Content is treated as `pre`: newlines split lines, tabs expand to
138
+ 8-column stops, nothing wraps.
139
+
140
+ ```svelte
141
+ <svt-ansi>{diffOutput}</svt-ansi>
142
+ ```
143
+
144
+ ## `<svt-region>`
145
+
146
+ A paint primitive whose cells come from your code — used to embed whole
147
+ terminal emulators (the playground's embedded-terminal demo). It fills its
148
+ box like a replaced element, receives a cell-source callback, and fires
149
+ `resize` with `{ cols, rows }` when its allocated size changes.