fb-slides 0.9.1 → 0.10.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/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ this — which makes it worth being able to see what arrived.
|
|
|
7
7
|
Entries are written as the work lands, under **Unreleased**; the release commit
|
|
8
8
|
that stamps the version renames that heading to the version and its date.
|
|
9
9
|
|
|
10
|
+
## 0.10.0 — 2026-09-08
|
|
11
|
+
|
|
12
|
+
- **A file in the assets panel opens on click.** The name on a row carries the
|
|
13
|
+
full path in its tooltip, and clicking it shows the file: an image comes up
|
|
14
|
+
right there, over the deck — full size, the path under it, a click anywhere
|
|
15
|
+
or Escape puts it away — and everything else opens in a new tab, where the
|
|
16
|
+
browser plays the clip, renders the PDF, and offers to save the rest.
|
|
17
|
+
|
|
10
18
|
## 0.9.1 — 2026-09-08
|
|
11
19
|
|
|
12
20
|
- **The assets panel shows the folder, not just what you dropped.** The list
|
package/package.json
CHANGED
package/runtime/assets.js
CHANGED
|
@@ -167,6 +167,32 @@ export const createAssets = ({ paste, active }) => {
|
|
|
167
167
|
const wordInput = confirmBox.querySelector('.deck-assets-word');
|
|
168
168
|
const confirmButton = confirmBox.querySelector('.deck-assets-confirm-delete');
|
|
169
169
|
|
|
170
|
+
// ---- the image preview --------------------------------------------------
|
|
171
|
+
// A click on an image's name opens the image itself, over everything — the
|
|
172
|
+
// drawer is narrow and a thumbnail would say less than the file name does.
|
|
173
|
+
// A click anywhere on it, or Escape, puts it away. Every other kind of file
|
|
174
|
+
// goes to a new tab instead: the browser knows a clip and a PDF better.
|
|
175
|
+
|
|
176
|
+
const preview = document.createElement('div');
|
|
177
|
+
preview.className = 'deck-assets-preview';
|
|
178
|
+
preview.hidden = true;
|
|
179
|
+
preview.innerHTML = `<figure><img alt="" /><figcaption><code></code></figcaption></figure>`;
|
|
180
|
+
const previewImage = preview.querySelector('img');
|
|
181
|
+
|
|
182
|
+
const openPreview = (path) => {
|
|
183
|
+
previewImage.src = path;
|
|
184
|
+
preview.querySelector('figcaption code').textContent = path;
|
|
185
|
+
preview.hidden = false;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const closePreview = () => {
|
|
189
|
+
preview.hidden = true;
|
|
190
|
+
// A 20 MB screenshot should stop arriving the moment nobody is looking.
|
|
191
|
+
previewImage.removeAttribute('src');
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
preview.addEventListener('click', closePreview);
|
|
195
|
+
|
|
170
196
|
// ---- the full-page sheet ----------------------------------------------
|
|
171
197
|
|
|
172
198
|
const overlay = document.createElement('div');
|
|
@@ -266,6 +292,7 @@ export const createAssets = ({ paste, active }) => {
|
|
|
266
292
|
nameRow.hidden = true;
|
|
267
293
|
waiting.hidden = true;
|
|
268
294
|
closeConfirm();
|
|
295
|
+
closePreview();
|
|
269
296
|
};
|
|
270
297
|
|
|
271
298
|
// ---- the rows ---------------------------------------------------------
|
|
@@ -309,10 +336,20 @@ export const createAssets = ({ paste, active }) => {
|
|
|
309
336
|
`<button type="button" class="deck-assets-insert" title="Write it into the slide">${INSERT_ICON}</button>` +
|
|
310
337
|
`<button type="button" class="deck-assets-trash" title="Delete the file">${TRASH_ICON}</button>` +
|
|
311
338
|
`</span>`;
|
|
312
|
-
row.querySelector('code')
|
|
339
|
+
const name = row.querySelector('code');
|
|
340
|
+
name.textContent = file.path;
|
|
313
341
|
// The drawer is narrow and a path can be long: the row truncates, and
|
|
314
|
-
// hovering
|
|
315
|
-
|
|
342
|
+
// hovering the name says the whole thing. Clicking it shows the file: an
|
|
343
|
+
// image right here, over the deck; anything else in a new tab, where the
|
|
344
|
+
// browser plays the clip, renders the PDF, and offers to save the rest.
|
|
345
|
+
name.title = file.path;
|
|
346
|
+
name.classList.add('is-viewable');
|
|
347
|
+
if (IMAGE.test(file.path)) {
|
|
348
|
+
name.classList.add('is-image');
|
|
349
|
+
name.addEventListener('click', () => openPreview(file.path));
|
|
350
|
+
} else {
|
|
351
|
+
name.addEventListener('click', () => window.open(file.path, '_blank', 'noopener'));
|
|
352
|
+
}
|
|
316
353
|
row.querySelector('.deck-assets-size').textContent = bytes(file.size);
|
|
317
354
|
row.querySelector('.deck-assets-copy').addEventListener('click', (event) =>
|
|
318
355
|
copy(file.path, event.currentTarget),
|
|
@@ -535,7 +572,7 @@ export const createAssets = ({ paste, active }) => {
|
|
|
535
572
|
drop([...event.dataTransfer.files], target?.dataset.dir ?? chosen);
|
|
536
573
|
});
|
|
537
574
|
|
|
538
|
-
document.body.append(overlay);
|
|
575
|
+
document.body.append(overlay, preview);
|
|
539
576
|
|
|
540
577
|
return {
|
|
541
578
|
element,
|
|
@@ -546,6 +583,7 @@ export const createAssets = ({ paste, active }) => {
|
|
|
546
583
|
// One layer per press, innermost first — the drawer asks this before it
|
|
547
584
|
// decides whether Escape was meant for it.
|
|
548
585
|
escape: () => {
|
|
586
|
+
if (!preview.hidden) return closePreview(), true;
|
|
549
587
|
if (!confirmBox.hidden) return closeConfirm(), true;
|
|
550
588
|
if (!element.hidden) return close(), true;
|
|
551
589
|
return false;
|
package/runtime/theme.base.css
CHANGED
|
@@ -1683,6 +1683,12 @@ body.edit-open #deck-edit { transform: none; }
|
|
|
1683
1683
|
text-overflow: ellipsis;
|
|
1684
1684
|
white-space: nowrap;
|
|
1685
1685
|
}
|
|
1686
|
+
/* A file's name shows the file — an image over the deck, the rest in a new
|
|
1687
|
+
tab; the cursor and the underline are the whole affordance, the row stays a
|
|
1688
|
+
row. */
|
|
1689
|
+
.deck-assets-list code.is-viewable { cursor: pointer; }
|
|
1690
|
+
.deck-assets-list code.is-image { cursor: zoom-in; }
|
|
1691
|
+
.deck-assets-list code.is-viewable:hover { color: var(--accent); text-decoration: underline; }
|
|
1686
1692
|
.deck-assets-file {
|
|
1687
1693
|
min-width: 0;
|
|
1688
1694
|
font: 400 12px/1.5 var(--sans);
|
|
@@ -1869,6 +1875,40 @@ body.edit-open #deck-edit { transform: none; }
|
|
|
1869
1875
|
transform: scale(1.04);
|
|
1870
1876
|
}
|
|
1871
1877
|
|
|
1878
|
+
/* The image preview — over everything the way the drop sheet is: the image is
|
|
1879
|
+
the whole point while it is up, and a click anywhere puts it away. */
|
|
1880
|
+
.deck-assets-preview {
|
|
1881
|
+
position: fixed;
|
|
1882
|
+
inset: 0;
|
|
1883
|
+
z-index: 72;
|
|
1884
|
+
display: grid;
|
|
1885
|
+
place-items: center;
|
|
1886
|
+
background: color-mix(in srgb, var(--bg) 74%, transparent);
|
|
1887
|
+
backdrop-filter: blur(8px);
|
|
1888
|
+
cursor: zoom-out;
|
|
1889
|
+
}
|
|
1890
|
+
.deck-assets-preview[hidden] { display: none; }
|
|
1891
|
+
.deck-assets-preview figure {
|
|
1892
|
+
margin: 0;
|
|
1893
|
+
display: flex;
|
|
1894
|
+
flex-direction: column;
|
|
1895
|
+
align-items: center;
|
|
1896
|
+
gap: 12px;
|
|
1897
|
+
}
|
|
1898
|
+
.deck-assets-preview img {
|
|
1899
|
+
max-width: min(1100px, 84vw);
|
|
1900
|
+
max-height: 78vh;
|
|
1901
|
+
border: 1px solid var(--line);
|
|
1902
|
+
border-radius: 10px;
|
|
1903
|
+
/* A card behind it, so a transparent PNG reads as an image and not a hole. */
|
|
1904
|
+
background: var(--card);
|
|
1905
|
+
box-shadow: 0 18px 60px color-mix(in srgb, #000 45%, transparent);
|
|
1906
|
+
}
|
|
1907
|
+
.deck-assets-preview figcaption code {
|
|
1908
|
+
font: 500 12.5px/1.4 var(--mono);
|
|
1909
|
+
color: var(--accent-2);
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1872
1912
|
/* The open drawer's button wears the accent — it draws in nothing, like the
|
|
1873
1913
|
pointer's; the id outweighs the generic armed-tool rule. */
|
|
1874
1914
|
#tool-edit[aria-pressed='true'] {
|
|
Binary file
|