@dogsbay/ui 0.2.0-beta.129 → 0.2.0-beta.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dogsbay/ui",
3
- "version": "0.2.0-beta.129",
3
+ "version": "0.2.0-beta.130",
4
4
  "description": "Accessible UI components for Astro, inspired by Base UI and shadcn",
5
5
  "type": "module",
6
6
  "exports": {
@@ -22,9 +22,9 @@
22
22
  "katex": "^0.16.47",
23
23
  "maplibre-gl": "^5.24.0",
24
24
  "shiki": "^4.3.1",
25
- "@dogsbay/elements": "0.2.0-beta.129",
26
- "@dogsbay/icons": "0.2.0-beta.129",
27
- "@dogsbay/primitives": "0.2.0-beta.129"
25
+ "@dogsbay/elements": "0.2.0-beta.130",
26
+ "@dogsbay/icons": "0.2.0-beta.130",
27
+ "@dogsbay/primitives": "0.2.0-beta.130"
28
28
  },
29
29
  "files": [
30
30
  "src",
@@ -64,6 +64,16 @@ interface Props {
64
64
  */
65
65
  diffAdd?: string;
66
66
  diffRemove?: string;
67
+ /**
68
+ * Lines to fold behind a toggle, e.g. "3-8,20-25" (Expressive Code's `collapse`), numbered from the
69
+ * block's first line (not `startLine`). Each run shows as "N collapsed lines"; a click or Space
70
+ * shows or hides it. No script: a checkbox in the label, and
71
+ * code-rich.css (render-html's code blocks use the same markup).
72
+ */
73
+ collapse?: string;
74
+ /** The toggle's text; `{n}` is the number of lines it hides. `collapsedLabelOne` for a single line. */
75
+ collapsedLabel?: string;
76
+ collapsedLabelOne?: string;
67
77
  class?: string;
68
78
  [key: string]: unknown;
69
79
  }
@@ -81,6 +91,9 @@ const {
81
91
  copyText: copyTextOverride,
82
92
  diffAdd,
83
93
  diffRemove,
94
+ collapse,
95
+ collapsedLabel = "{n} collapsed lines",
96
+ collapsedLabelOne = "1 collapsed line",
84
97
  class: className,
85
98
  ...rest
86
99
  } = Astro.props;
@@ -93,7 +106,8 @@ const parseLineSpec = (spec?: string): Set<number> => {
93
106
  if (!range) continue;
94
107
  const start = Number(range[1]);
95
108
  const end = range[2] ? Number(range[2]) : start;
96
- for (let n = start; n <= end; n++) out.add(n);
109
+ // Capped as render-html's parseLineRanges: `1-999999999` would fill the Set and stall the build
110
+ for (let n = start; n <= Math.min(end, start + 5000); n++) out.add(n);
97
111
  }
98
112
  return out;
99
113
  };
@@ -182,6 +196,48 @@ transformers.push({
182
196
  },
183
197
  });
184
198
 
199
+ // Collapsed runs: after the gutter, so each folded line keeps its number. Lines are the
200
+ // `.line` spans of <code>, separated by "\n" text nodes (render-html's collapseLines does the same).
201
+ const collapseRuns: Array<[number, number]> = [];
202
+ for (const n of [...parseLineSpec(collapse)].sort((a, b) => a - b)) {
203
+ const last = collapseRuns[collapseRuns.length - 1];
204
+ if (last && n === last[1] + 1) last[1] = n;
205
+ else collapseRuns.push([n, n]);
206
+ }
207
+ if (collapseRuns.length) {
208
+ transformers.push({
209
+ name: "collapse",
210
+ code(node) {
211
+ const kids = node.children as any[];
212
+ const linePos = kids.flatMap((c, i) => (c.type === "element" && c.tagName === "span" ? [i] : []));
213
+ for (const [a, b] of [...collapseRuns].reverse()) {
214
+ if (a > linePos.length) continue;
215
+ const end = Math.min(b, linePos.length);
216
+ const from = linePos[a - 1];
217
+ const to = linePos[end - 1];
218
+ const label = (end === a ? collapsedLabelOne : collapsedLabel).replace("{n}", String(end - a + 1));
219
+ kids.splice(from, to - from + 1, {
220
+ type: "element",
221
+ tagName: "span",
222
+ properties: { class: "code-collapse" },
223
+ children: [
224
+ {
225
+ type: "element",
226
+ tagName: "label",
227
+ properties: { class: "code-collapse-label", "data-pagefind-ignore": "" },
228
+ children: [
229
+ { type: "element", tagName: "input", properties: { type: "checkbox", class: "code-collapse-toggle" }, children: [] },
230
+ { type: "text", value: label },
231
+ ],
232
+ },
233
+ { type: "element", tagName: "span", properties: { class: "code-collapse-lines" }, children: kids.slice(from, to + 1) },
234
+ ],
235
+ });
236
+ }
237
+ },
238
+ });
239
+ }
240
+
185
241
  // Build meta string
186
242
  let metaStr = "";
187
243
  if (highlights) metaStr += `{${highlights}} `;
@@ -85,3 +85,36 @@
85
85
  padding: 1px 4px;
86
86
  margin: 0 -1px;
87
87
  }
88
+
89
+ /* ── `collapse` fence option: line runs folded behind a toggle ──
90
+ No script: a checkbox inside the label. Lines hide only where :has() works,
91
+ so a browser without it shows every line rather than losing them. */
92
+ .code-rich-body .code-collapse-label {
93
+ display: inline-block;
94
+ width: 100%;
95
+ cursor: pointer;
96
+ user-select: none;
97
+ /* The code's own colour: a muted label fell under 4.5:1 on the code background */
98
+ border-block: 1px dashed color-mix(in oklab, currentColor 35%, transparent);
99
+ font-style: italic;
100
+ }
101
+ .code-rich-body .code-collapse-toggle {
102
+ position: absolute;
103
+ width: 1px;
104
+ height: 1px;
105
+ opacity: 0;
106
+ }
107
+ .code-rich-body .code-collapse-label:has(.code-collapse-toggle:focus-visible) {
108
+ outline: 2px solid var(--ring);
109
+ outline-offset: -2px;
110
+ }
111
+ /* The label stays when open, so focus stays on the checkbox and it folds again */
112
+ .code-rich-body .code-collapse-label::before {
113
+ content: "▸ ";
114
+ }
115
+ .code-rich-body .code-collapse-label:has(.code-collapse-toggle:checked)::before {
116
+ content: "▾ ";
117
+ }
118
+ .code-rich-body .code-collapse:has(.code-collapse-toggle:not(:checked)) > .code-collapse-lines {
119
+ display: none;
120
+ }
@@ -119,4 +119,9 @@ const { class: className, ...rest } = Astro.props;
119
119
  background: var(--color-border);
120
120
  opacity: 0.6;
121
121
  }
122
+
123
+ /* A step's title on its own line, above its detail (format-astro and render-html mark it) */
124
+ .steps-list > :global(li) > :global(.step-title) {
125
+ display: block;
126
+ }
122
127
  </style>
@@ -70,4 +70,9 @@ const { class: className, ...rest } = Astro.props;
70
70
  background: var(--color-border);
71
71
  opacity: 0.6;
72
72
  }
73
+
74
+ /* A step's title on its own line, above its detail (format-astro and render-html mark it) */
75
+ .sub-steps-list > :global(li) > :global(.step-title) {
76
+ display: block;
77
+ }
73
78
  </style>