@wildwinter/app-shell 0.40.1 → 0.41.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/README.md +37 -0
- package/dist/chunk-BZ3MQDWM.js +153 -0
- package/dist/chunk-BZ3MQDWM.js.map +1 -0
- package/dist/index.cjs +148 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/kit-gallery.cjs +369 -0
- package/dist/kit-gallery.cjs.map +1 -0
- package/dist/kit-gallery.css +179 -0
- package/dist/kit-gallery.css.map +1 -0
- package/dist/kit-gallery.d.cts +64 -0
- package/dist/kit-gallery.d.ts +64 -0
- package/dist/kit-gallery.js +6 -0
- package/dist/kit-gallery.js.map +1 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -144,6 +144,43 @@ needing and never had.
|
|
|
144
144
|
anywhere: "all is well" was being met with raw green literals that could not
|
|
145
145
|
theme-shift.
|
|
146
146
|
|
|
147
|
+
## v0.41 (the kit gallery)
|
|
148
|
+
|
|
149
|
+
The new-thing moment (New Project, New Box, New Scene), drawn once: tiles on
|
|
150
|
+
the left, the chosen kit said in full on the right, one screen, on the dialog
|
|
151
|
+
frame. Shelves say what their button does, so a kit ("Create") and a worked
|
|
152
|
+
example ("Open a Copy") can sit side by side.
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import { openKitGallery } from "@wildwinter/app-shell";
|
|
156
|
+
import "@wildwinter/app-shell/kit-gallery.css";
|
|
157
|
+
|
|
158
|
+
openKitGallery({
|
|
159
|
+
title: "New project",
|
|
160
|
+
what: "A project is one game's worth of storylets.",
|
|
161
|
+
namePlaceholder: "The Village",
|
|
162
|
+
details: vcsFields, // the app's own fields, under the name
|
|
163
|
+
sections: [
|
|
164
|
+
{ caption: "Start from a kit", items: [
|
|
165
|
+
{ id: "starter", name: "Starter project", blurb: "Two cards that already work together.",
|
|
166
|
+
play: "Press Play: one card opens the next.", lands: ["One box", "Two cards"] },
|
|
167
|
+
] },
|
|
168
|
+
{ caption: "Learn from a finished project", action: "Open a Copy", usesDetails: false,
|
|
169
|
+
items: [{ id: "hamlet", name: "The Hamlet", blurb: "Small.", badge: "Start here" }] },
|
|
170
|
+
],
|
|
171
|
+
onPick: (id, { name }) => { /* the app makes it */ },
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
- **What a kit is made of stays in the app.** The shell knows names, words and
|
|
176
|
+
pictures, never boxes or scenes.
|
|
177
|
+
- **Pictures are masks.** `image` is a transparent file whose opaque pixels are
|
|
178
|
+
the ink, drawn in `--kit-art-ink` on `--kit-art-plate`. A dark theme sets a
|
|
179
|
+
paper-toned plate and a dark ink rather than inverting, which turns an
|
|
180
|
+
engraving into a photographic negative.
|
|
181
|
+
- Single click chooses, double-click chooses and goes, Enter in the name field
|
|
182
|
+
creates; the name is required when asked for.
|
|
183
|
+
|
|
147
184
|
## Roadmap
|
|
148
185
|
|
|
149
186
|
Later slices lift the rest of the common shell from Patterpad (canonical),
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { dialogFrame } from './chunk-YRFJLJUH.js';
|
|
2
|
+
import { el } from './chunk-UG2P777F.js';
|
|
3
|
+
|
|
4
|
+
// src/kit-gallery.ts
|
|
5
|
+
function openKitGallery(opts) {
|
|
6
|
+
const frame = dialogFrame({ title: opts.title, ...opts.what !== void 0 ? { sub: opts.what } : {}, className: "kit-gallery", ...opts.onClose ? { onClose: opts.onClose } : {} });
|
|
7
|
+
const { dialog } = frame;
|
|
8
|
+
const entries = opts.sections.flatMap((section, s) => section.items.map((item) => ({ item, section, s })));
|
|
9
|
+
if (entries.length === 0) throw new Error("openKitGallery: no items to choose from");
|
|
10
|
+
let chosen = entries.find((e) => e.item.id === opts.initial) ?? entries[0];
|
|
11
|
+
const nameInput = opts.namePlaceholder === void 0 ? void 0 : el("input", { className: "field kit-gallery-name" });
|
|
12
|
+
if (nameInput) {
|
|
13
|
+
nameInput.placeholder = opts.namePlaceholder;
|
|
14
|
+
nameInput.setAttribute("aria-label", opts.nameLabel ?? "Name");
|
|
15
|
+
}
|
|
16
|
+
const fields = el(
|
|
17
|
+
"div",
|
|
18
|
+
"kit-gallery-fields",
|
|
19
|
+
...nameInput ? [el("label", "kit-gallery-label", opts.nameLabel ?? "Name"), nameInput] : [],
|
|
20
|
+
...opts.details ? [opts.details] : []
|
|
21
|
+
);
|
|
22
|
+
const panelArt = el("div", "kit-gallery-art kit-gallery-panel-art");
|
|
23
|
+
const panelName = el("h3", "kit-gallery-panel-name");
|
|
24
|
+
const panelBlurb = el("p", "kit-gallery-panel-blurb");
|
|
25
|
+
const panelDetail = el("p", "kit-gallery-panel-detail");
|
|
26
|
+
const panelPlay = el("p", "kit-gallery-play");
|
|
27
|
+
const panelShows = el("p", "kit-gallery-shows");
|
|
28
|
+
const panelLands = el("ul", "kit-gallery-lands");
|
|
29
|
+
const panelLandsCaption = el("p", "kit-gallery-lands-caption", "What you get");
|
|
30
|
+
const panelNote = el("p", "kit-gallery-note");
|
|
31
|
+
const panel = el(
|
|
32
|
+
"div",
|
|
33
|
+
"kit-gallery-panel",
|
|
34
|
+
panelArt,
|
|
35
|
+
panelName,
|
|
36
|
+
panelBlurb,
|
|
37
|
+
panelDetail,
|
|
38
|
+
panelPlay,
|
|
39
|
+
panelShows,
|
|
40
|
+
panelLandsCaption,
|
|
41
|
+
panelLands,
|
|
42
|
+
panelNote,
|
|
43
|
+
fields
|
|
44
|
+
);
|
|
45
|
+
const primary = el("button", { className: "btn primary", onClick: () => commit() });
|
|
46
|
+
primary.type = "button";
|
|
47
|
+
const cancel = el("button", { className: "btn", text: "Cancel", onClick: () => frame.close() });
|
|
48
|
+
cancel.type = "button";
|
|
49
|
+
const setArt = (host, image) => {
|
|
50
|
+
host.replaceChildren();
|
|
51
|
+
host.hidden = image === void 0;
|
|
52
|
+
if (image === void 0) return;
|
|
53
|
+
const ink = el("span", "kit-gallery-ink");
|
|
54
|
+
ink.style.setProperty("--kit-art", `url("${image.replace(/"/g, "%22")}")`);
|
|
55
|
+
host.append(ink);
|
|
56
|
+
};
|
|
57
|
+
const setText = (node, text) => {
|
|
58
|
+
node.textContent = text ?? "";
|
|
59
|
+
node.hidden = text === void 0 || text === "";
|
|
60
|
+
};
|
|
61
|
+
const tiles = /* @__PURE__ */ new Map();
|
|
62
|
+
const shelves = opts.sections.map((section) => {
|
|
63
|
+
const grid = el("div", "kit-gallery-grid", ...section.items.map((item) => {
|
|
64
|
+
const art = el("div", "kit-gallery-art");
|
|
65
|
+
setArt(art, item.image);
|
|
66
|
+
const tile = el(
|
|
67
|
+
"button",
|
|
68
|
+
{ className: "kit-gallery-tile", onClick: () => choose(item.id) },
|
|
69
|
+
art,
|
|
70
|
+
el(
|
|
71
|
+
"span",
|
|
72
|
+
"kit-gallery-tile-head",
|
|
73
|
+
el("span", "kit-gallery-tile-name", item.name),
|
|
74
|
+
item.badge !== void 0 ? el("span", "kit-gallery-badge", item.badge) : null
|
|
75
|
+
),
|
|
76
|
+
el("span", "kit-gallery-tile-blurb", item.blurb)
|
|
77
|
+
);
|
|
78
|
+
tile.type = "button";
|
|
79
|
+
tile.dataset.kit = item.id;
|
|
80
|
+
tile.addEventListener("dblclick", () => {
|
|
81
|
+
choose(item.id);
|
|
82
|
+
commit();
|
|
83
|
+
});
|
|
84
|
+
tiles.set(item.id, tile);
|
|
85
|
+
return tile;
|
|
86
|
+
}));
|
|
87
|
+
return el(
|
|
88
|
+
"section",
|
|
89
|
+
"kit-gallery-shelf",
|
|
90
|
+
section.caption !== void 0 ? el("h3", "kit-gallery-caption", section.caption) : null,
|
|
91
|
+
section.note !== void 0 ? el("p", "kit-gallery-shelf-note", section.note) : null,
|
|
92
|
+
grid
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
const choose = (id) => {
|
|
96
|
+
const next = entries.find((e) => e.item.id === id);
|
|
97
|
+
if (!next) return;
|
|
98
|
+
chosen = next;
|
|
99
|
+
for (const [tid, tile] of tiles) tile.setAttribute("aria-pressed", String(tid === id));
|
|
100
|
+
const { item, section } = chosen;
|
|
101
|
+
setArt(panelArt, item.image);
|
|
102
|
+
panelName.textContent = item.name;
|
|
103
|
+
setText(panelBlurb, item.blurb);
|
|
104
|
+
setText(panelDetail, item.detail);
|
|
105
|
+
setText(panelPlay, item.play);
|
|
106
|
+
setText(panelShows, item.shows !== void 0 ? `Shows: ${item.shows}` : void 0);
|
|
107
|
+
panelLands.replaceChildren(...(item.lands ?? []).map((l) => el("li", void 0, l)));
|
|
108
|
+
panelLands.hidden = (item.lands ?? []).length === 0;
|
|
109
|
+
panelLandsCaption.hidden = panelLands.hidden;
|
|
110
|
+
const details = section.usesDetails !== false;
|
|
111
|
+
fields.hidden = !details || nameInput === void 0 && opts.details === void 0;
|
|
112
|
+
setText(panelNote, details ? void 0 : section.note);
|
|
113
|
+
primary.textContent = section.action ?? "Create";
|
|
114
|
+
};
|
|
115
|
+
const commit = () => {
|
|
116
|
+
const { item, section } = chosen;
|
|
117
|
+
const details = section.usesDetails !== false;
|
|
118
|
+
let name;
|
|
119
|
+
if (details && nameInput) {
|
|
120
|
+
name = nameInput.value.trim();
|
|
121
|
+
if (name === "") {
|
|
122
|
+
nameInput.focus();
|
|
123
|
+
nameInput.classList.add("kit-gallery-missing");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
frame.close();
|
|
128
|
+
opts.onPick(item.id, name !== void 0 ? { name } : {});
|
|
129
|
+
};
|
|
130
|
+
if (nameInput) {
|
|
131
|
+
nameInput.addEventListener("input", () => nameInput.classList.remove("kit-gallery-missing"));
|
|
132
|
+
nameInput.addEventListener("keydown", (e) => {
|
|
133
|
+
e.stopPropagation();
|
|
134
|
+
if (e.key !== "Enter") return;
|
|
135
|
+
e.preventDefault();
|
|
136
|
+
commit();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
frame.body.append(el("div", "kit-gallery-layout", el("div", "kit-gallery-shelves", ...shelves), panel));
|
|
140
|
+
frame.actions.append(cancel, primary);
|
|
141
|
+
dialog.addEventListener("click", (e) => {
|
|
142
|
+
if (e.target === dialog) frame.close();
|
|
143
|
+
});
|
|
144
|
+
choose(chosen.item.id);
|
|
145
|
+
frame.open();
|
|
146
|
+
if (nameInput && chosen.section.usesDetails !== false) nameInput.focus();
|
|
147
|
+
else tiles.get(chosen.item.id)?.focus();
|
|
148
|
+
return { dialog, close: () => frame.close() };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { openKitGallery };
|
|
152
|
+
//# sourceMappingURL=chunk-BZ3MQDWM.js.map
|
|
153
|
+
//# sourceMappingURL=chunk-BZ3MQDWM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/kit-gallery.ts"],"names":[],"mappings":"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","file":"chunk-BZ3MQDWM.js","sourcesContent":["// ---------------------------------------------------------------------------\n// The kit gallery: pick a starting point by what you want to make.\n//\n// The new-thing moment for the family (New Project, New Box, New Scene), drawn\n// once. Adobe's New Document is the shape: tiles on the left, a details panel\n// on the right, one screen. Not a wizard: a wizard asks for settings before\n// anything has been chosen, and the choice is the part that teaches.\n//\n// Storyletter grew this as `kit-picker.ts` (one component at two scales on\n// <dialog>, \"a shell candidate, held back until it had been used in earnest\")\n// and the kit gallery brief moved it here, 2026-09-27\n// (storylet-studio/design/kit-gallery.md). What a kit IS made of stays in\n// each app: this file knows names, words and pictures, never boxes or scenes.\n//\n// Sections are shelves (\"Start from a kit\", \"Learn from a finished project\"),\n// and each says what its button does, because opening a copy of an example\n// and creating from a kit are different acts behind the same kind of tile.\n// The app's own fields (a project name, version control, a build path) sit in\n// the details panel, shown only for the sections that use them.\n// ---------------------------------------------------------------------------\n\nimport { el } from \"./dom.js\";\nimport { dialogFrame } from \"./dialog.js\";\n\nexport interface KitGalleryItem<T extends string> {\n id: T;\n /** What you are making, in the author's terms, not the model's. */\n name: string;\n /** What it is FOR: one line on the tile, and the panel's first line. */\n blurb: string;\n /** More, for the panel only. */\n detail?: string;\n /** What pressing Play (or Run) shows, said as a promise. */\n play?: string;\n /** The model's parts it puts to work, second and quieter (\"Shows: ...\"). */\n shows?: string;\n /** What lands, in the concrete, as a short list in the panel. */\n lands?: string[];\n /** A word or two on the tile (\"Start here\"). */\n badge?: string;\n /** An illustration: a transparent image whose opaque pixels are the ink.\n * Drawn as a mask in `--kit-art-ink` on `--kit-art-plate`, so one file\n * serves both themes and the app chooses the colours. */\n image?: string;\n}\n\nexport interface KitGallerySection<T extends string> {\n /** Sentence-case label text (\"Start from a kit\"). Absent: no caption. */\n caption?: string;\n /** The consequence of a click, said before the click. */\n note?: string;\n items: KitGalleryItem<T>[];\n /** The primary button's label while an item here is chosen. Default \"Create\". */\n action?: string;\n /** Show the app's detail fields (and ask for the name) for this section.\n * Default true. An example is opened, not named, so its shelf says false. */\n usesDetails?: boolean;\n}\n\nexport interface KitGalleryChoice {\n /** Present when a name was asked for and the chosen section uses details. */\n name?: string;\n}\n\nexport interface KitGalleryOptions<T extends string> {\n /** The dialog's heading: \"New project\", \"New box\", \"New scene\". */\n title: string;\n /** What the thing being made IS, in concrete terms. */\n what?: string;\n sections: KitGallerySection<T>[];\n /** Ask for a name in the details panel, with this placeholder. Required\n * when asked: making a thing without one would have to invent a folder. */\n namePlaceholder?: string;\n /** The name field's label. Default \"Name\". */\n nameLabel?: string;\n /** The app's own fields, below the name (version control, a build path). */\n details?: HTMLElement;\n /** The item chosen when the gallery opens. Default: the first. */\n initial?: T;\n onPick: (id: T, choice: KitGalleryChoice) => void;\n /** Runs once the gallery has closed, whichever way. */\n onClose?: () => void;\n}\n\nexport interface KitGallery {\n readonly dialog: HTMLDialogElement;\n close(): void;\n}\n\n/** Open the gallery as a modal dialog on the family's frame. */\nexport function openKitGallery<T extends string>(opts: KitGalleryOptions<T>): KitGallery {\n const frame = dialogFrame({ title: opts.title, ...(opts.what !== undefined ? { sub: opts.what } : {}), className: \"kit-gallery\", ...(opts.onClose ? { onClose: opts.onClose } : {}) });\n const { dialog } = frame;\n\n const entries = opts.sections.flatMap((section, s) => section.items.map((item) => ({ item, section, s })));\n if (entries.length === 0) throw new Error(\"openKitGallery: no items to choose from\");\n let chosen = entries.find((e) => e.item.id === opts.initial) ?? entries[0]!;\n\n // --- the details panel ----------------------------------------------------\n const nameInput = opts.namePlaceholder === undefined ? undefined : el(\"input\", { className: \"field kit-gallery-name\" }) as HTMLInputElement;\n if (nameInput) {\n nameInput.placeholder = opts.namePlaceholder!;\n nameInput.setAttribute(\"aria-label\", opts.nameLabel ?? \"Name\");\n }\n const fields = el(\"div\", \"kit-gallery-fields\",\n ...(nameInput ? [el(\"label\", \"kit-gallery-label\", opts.nameLabel ?? \"Name\"), nameInput] : []),\n ...(opts.details ? [opts.details] : []));\n\n const panelArt = el(\"div\", \"kit-gallery-art kit-gallery-panel-art\");\n const panelName = el(\"h3\", \"kit-gallery-panel-name\");\n const panelBlurb = el(\"p\", \"kit-gallery-panel-blurb\");\n const panelDetail = el(\"p\", \"kit-gallery-panel-detail\");\n const panelPlay = el(\"p\", \"kit-gallery-play\");\n const panelShows = el(\"p\", \"kit-gallery-shows\");\n const panelLands = el(\"ul\", \"kit-gallery-lands\");\n const panelLandsCaption = el(\"p\", \"kit-gallery-lands-caption\", \"What you get\");\n const panelNote = el(\"p\", \"kit-gallery-note\");\n const panel = el(\"div\", \"kit-gallery-panel\",\n panelArt, panelName, panelBlurb, panelDetail, panelPlay, panelShows, panelLandsCaption, panelLands, panelNote, fields);\n\n const primary = el(\"button\", { className: \"btn primary\", onClick: () => commit() }) as HTMLButtonElement;\n primary.type = \"button\";\n const cancel = el(\"button\", { className: \"btn\", text: \"Cancel\", onClick: () => frame.close() }) as HTMLButtonElement;\n cancel.type = \"button\";\n\n const setArt = (host: HTMLElement, image: string | undefined): void => {\n host.replaceChildren();\n host.hidden = image === undefined;\n if (image === undefined) return;\n const ink = el(\"span\", \"kit-gallery-ink\");\n ink.style.setProperty(\"--kit-art\", `url(\"${image.replace(/\"/g, \"%22\")}\")`);\n host.append(ink);\n };\n const setText = (node: HTMLElement, text: string | undefined): void => {\n node.textContent = text ?? \"\";\n node.hidden = text === undefined || text === \"\";\n };\n\n // --- the tiles --------------------------------------------------------------\n const tiles = new Map<T, HTMLButtonElement>();\n const shelves = opts.sections.map((section) => {\n const grid = el(\"div\", \"kit-gallery-grid\", ...section.items.map((item) => {\n const art = el(\"div\", \"kit-gallery-art\");\n setArt(art, item.image);\n const tile = el(\"button\", { className: \"kit-gallery-tile\", onClick: () => choose(item.id) },\n art,\n el(\"span\", \"kit-gallery-tile-head\",\n el(\"span\", \"kit-gallery-tile-name\", item.name),\n item.badge !== undefined ? el(\"span\", \"kit-gallery-badge\", item.badge) : null),\n el(\"span\", \"kit-gallery-tile-blurb\", item.blurb)) as HTMLButtonElement;\n tile.type = \"button\";\n tile.dataset.kit = item.id;\n // Double-click is the desktop's \"choose and go\"; a single click only chooses,\n // so a tile can be read in the panel before anything is made.\n tile.addEventListener(\"dblclick\", () => { choose(item.id); commit(); });\n tiles.set(item.id, tile);\n return tile;\n }));\n return el(\"section\", \"kit-gallery-shelf\",\n section.caption !== undefined ? el(\"h3\", \"kit-gallery-caption\", section.caption) : null,\n section.note !== undefined ? el(\"p\", \"kit-gallery-shelf-note\", section.note) : null,\n grid);\n });\n\n const choose = (id: T): void => {\n const next = entries.find((e) => e.item.id === id);\n if (!next) return;\n chosen = next;\n for (const [tid, tile] of tiles) tile.setAttribute(\"aria-pressed\", String(tid === id));\n const { item, section } = chosen;\n setArt(panelArt, item.image);\n panelName.textContent = item.name;\n setText(panelBlurb, item.blurb);\n setText(panelDetail, item.detail);\n setText(panelPlay, item.play);\n setText(panelShows, item.shows !== undefined ? `Shows: ${item.shows}` : undefined);\n panelLands.replaceChildren(...(item.lands ?? []).map((l) => el(\"li\", undefined, l)));\n panelLands.hidden = (item.lands ?? []).length === 0;\n panelLandsCaption.hidden = panelLands.hidden;\n const details = section.usesDetails !== false;\n fields.hidden = !details || (nameInput === undefined && opts.details === undefined);\n // Without the fields, the shelf's note is what the click will do next\n // (\"a folder you choose\"), so the panel repeats it beside the button.\n setText(panelNote, details ? undefined : section.note);\n primary.textContent = section.action ?? \"Create\";\n };\n\n const commit = (): void => {\n const { item, section } = chosen;\n const details = section.usesDetails !== false;\n let name: string | undefined;\n if (details && nameInput) {\n name = nameInput.value.trim();\n if (name === \"\") { nameInput.focus(); nameInput.classList.add(\"kit-gallery-missing\"); return; }\n }\n frame.close();\n opts.onPick(item.id, name !== undefined ? { name } : {});\n };\n\n if (nameInput) {\n nameInput.addEventListener(\"input\", () => nameInput.classList.remove(\"kit-gallery-missing\"));\n // Enter creates with what is chosen: the author has said what it should be\n // called, and the tile they are looking at is the one they meant.\n nameInput.addEventListener(\"keydown\", (e) => {\n e.stopPropagation();\n if (e.key !== \"Enter\") return;\n e.preventDefault();\n commit();\n });\n }\n\n frame.body.append(el(\"div\", \"kit-gallery-layout\", el(\"div\", \"kit-gallery-shelves\", ...shelves), panel));\n frame.actions.append(cancel, primary);\n dialog.addEventListener(\"click\", (e) => { if (e.target === dialog) frame.close(); });\n\n choose(chosen.item.id);\n frame.open();\n // Focus where the next keystroke is wanted: the name when one is asked for\n // and the opening shelf uses it, otherwise the chosen tile.\n if (nameInput && chosen.section.usesDetails !== false) nameInput.focus();\n else tiles.get(chosen.item.id)?.focus();\n\n return { dialog, close: () => frame.close() };\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -2763,6 +2763,153 @@ function mountWelcome(host, opts) {
|
|
|
2763
2763
|
return { el: root, setRecents: drawRecents, setError };
|
|
2764
2764
|
}
|
|
2765
2765
|
|
|
2766
|
+
// src/kit-gallery.ts
|
|
2767
|
+
function openKitGallery(opts) {
|
|
2768
|
+
const frame = dialogFrame({ title: opts.title, ...opts.what !== void 0 ? { sub: opts.what } : {}, className: "kit-gallery", ...opts.onClose ? { onClose: opts.onClose } : {} });
|
|
2769
|
+
const { dialog } = frame;
|
|
2770
|
+
const entries = opts.sections.flatMap((section, s) => section.items.map((item) => ({ item, section, s })));
|
|
2771
|
+
if (entries.length === 0) throw new Error("openKitGallery: no items to choose from");
|
|
2772
|
+
let chosen = entries.find((e) => e.item.id === opts.initial) ?? entries[0];
|
|
2773
|
+
const nameInput = opts.namePlaceholder === void 0 ? void 0 : el("input", { className: "field kit-gallery-name" });
|
|
2774
|
+
if (nameInput) {
|
|
2775
|
+
nameInput.placeholder = opts.namePlaceholder;
|
|
2776
|
+
nameInput.setAttribute("aria-label", opts.nameLabel ?? "Name");
|
|
2777
|
+
}
|
|
2778
|
+
const fields = el(
|
|
2779
|
+
"div",
|
|
2780
|
+
"kit-gallery-fields",
|
|
2781
|
+
...nameInput ? [el("label", "kit-gallery-label", opts.nameLabel ?? "Name"), nameInput] : [],
|
|
2782
|
+
...opts.details ? [opts.details] : []
|
|
2783
|
+
);
|
|
2784
|
+
const panelArt = el("div", "kit-gallery-art kit-gallery-panel-art");
|
|
2785
|
+
const panelName = el("h3", "kit-gallery-panel-name");
|
|
2786
|
+
const panelBlurb = el("p", "kit-gallery-panel-blurb");
|
|
2787
|
+
const panelDetail = el("p", "kit-gallery-panel-detail");
|
|
2788
|
+
const panelPlay = el("p", "kit-gallery-play");
|
|
2789
|
+
const panelShows = el("p", "kit-gallery-shows");
|
|
2790
|
+
const panelLands = el("ul", "kit-gallery-lands");
|
|
2791
|
+
const panelLandsCaption = el("p", "kit-gallery-lands-caption", "What you get");
|
|
2792
|
+
const panelNote = el("p", "kit-gallery-note");
|
|
2793
|
+
const panel = el(
|
|
2794
|
+
"div",
|
|
2795
|
+
"kit-gallery-panel",
|
|
2796
|
+
panelArt,
|
|
2797
|
+
panelName,
|
|
2798
|
+
panelBlurb,
|
|
2799
|
+
panelDetail,
|
|
2800
|
+
panelPlay,
|
|
2801
|
+
panelShows,
|
|
2802
|
+
panelLandsCaption,
|
|
2803
|
+
panelLands,
|
|
2804
|
+
panelNote,
|
|
2805
|
+
fields
|
|
2806
|
+
);
|
|
2807
|
+
const primary = el("button", { className: "btn primary", onClick: () => commit() });
|
|
2808
|
+
primary.type = "button";
|
|
2809
|
+
const cancel = el("button", { className: "btn", text: "Cancel", onClick: () => frame.close() });
|
|
2810
|
+
cancel.type = "button";
|
|
2811
|
+
const setArt = (host, image) => {
|
|
2812
|
+
host.replaceChildren();
|
|
2813
|
+
host.hidden = image === void 0;
|
|
2814
|
+
if (image === void 0) return;
|
|
2815
|
+
const ink = el("span", "kit-gallery-ink");
|
|
2816
|
+
ink.style.setProperty("--kit-art", `url("${image.replace(/"/g, "%22")}")`);
|
|
2817
|
+
host.append(ink);
|
|
2818
|
+
};
|
|
2819
|
+
const setText = (node2, text) => {
|
|
2820
|
+
node2.textContent = text ?? "";
|
|
2821
|
+
node2.hidden = text === void 0 || text === "";
|
|
2822
|
+
};
|
|
2823
|
+
const tiles = /* @__PURE__ */ new Map();
|
|
2824
|
+
const shelves = opts.sections.map((section) => {
|
|
2825
|
+
const grid = el("div", "kit-gallery-grid", ...section.items.map((item) => {
|
|
2826
|
+
const art = el("div", "kit-gallery-art");
|
|
2827
|
+
setArt(art, item.image);
|
|
2828
|
+
const tile = el(
|
|
2829
|
+
"button",
|
|
2830
|
+
{ className: "kit-gallery-tile", onClick: () => choose(item.id) },
|
|
2831
|
+
art,
|
|
2832
|
+
el(
|
|
2833
|
+
"span",
|
|
2834
|
+
"kit-gallery-tile-head",
|
|
2835
|
+
el("span", "kit-gallery-tile-name", item.name),
|
|
2836
|
+
item.badge !== void 0 ? el("span", "kit-gallery-badge", item.badge) : null
|
|
2837
|
+
),
|
|
2838
|
+
el("span", "kit-gallery-tile-blurb", item.blurb)
|
|
2839
|
+
);
|
|
2840
|
+
tile.type = "button";
|
|
2841
|
+
tile.dataset.kit = item.id;
|
|
2842
|
+
tile.addEventListener("dblclick", () => {
|
|
2843
|
+
choose(item.id);
|
|
2844
|
+
commit();
|
|
2845
|
+
});
|
|
2846
|
+
tiles.set(item.id, tile);
|
|
2847
|
+
return tile;
|
|
2848
|
+
}));
|
|
2849
|
+
return el(
|
|
2850
|
+
"section",
|
|
2851
|
+
"kit-gallery-shelf",
|
|
2852
|
+
section.caption !== void 0 ? el("h3", "kit-gallery-caption", section.caption) : null,
|
|
2853
|
+
section.note !== void 0 ? el("p", "kit-gallery-shelf-note", section.note) : null,
|
|
2854
|
+
grid
|
|
2855
|
+
);
|
|
2856
|
+
});
|
|
2857
|
+
const choose = (id) => {
|
|
2858
|
+
const next = entries.find((e) => e.item.id === id);
|
|
2859
|
+
if (!next) return;
|
|
2860
|
+
chosen = next;
|
|
2861
|
+
for (const [tid, tile] of tiles) tile.setAttribute("aria-pressed", String(tid === id));
|
|
2862
|
+
const { item, section } = chosen;
|
|
2863
|
+
setArt(panelArt, item.image);
|
|
2864
|
+
panelName.textContent = item.name;
|
|
2865
|
+
setText(panelBlurb, item.blurb);
|
|
2866
|
+
setText(panelDetail, item.detail);
|
|
2867
|
+
setText(panelPlay, item.play);
|
|
2868
|
+
setText(panelShows, item.shows !== void 0 ? `Shows: ${item.shows}` : void 0);
|
|
2869
|
+
panelLands.replaceChildren(...(item.lands ?? []).map((l) => el("li", void 0, l)));
|
|
2870
|
+
panelLands.hidden = (item.lands ?? []).length === 0;
|
|
2871
|
+
panelLandsCaption.hidden = panelLands.hidden;
|
|
2872
|
+
const details = section.usesDetails !== false;
|
|
2873
|
+
fields.hidden = !details || nameInput === void 0 && opts.details === void 0;
|
|
2874
|
+
setText(panelNote, details ? void 0 : section.note);
|
|
2875
|
+
primary.textContent = section.action ?? "Create";
|
|
2876
|
+
};
|
|
2877
|
+
const commit = () => {
|
|
2878
|
+
const { item, section } = chosen;
|
|
2879
|
+
const details = section.usesDetails !== false;
|
|
2880
|
+
let name;
|
|
2881
|
+
if (details && nameInput) {
|
|
2882
|
+
name = nameInput.value.trim();
|
|
2883
|
+
if (name === "") {
|
|
2884
|
+
nameInput.focus();
|
|
2885
|
+
nameInput.classList.add("kit-gallery-missing");
|
|
2886
|
+
return;
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
frame.close();
|
|
2890
|
+
opts.onPick(item.id, name !== void 0 ? { name } : {});
|
|
2891
|
+
};
|
|
2892
|
+
if (nameInput) {
|
|
2893
|
+
nameInput.addEventListener("input", () => nameInput.classList.remove("kit-gallery-missing"));
|
|
2894
|
+
nameInput.addEventListener("keydown", (e) => {
|
|
2895
|
+
e.stopPropagation();
|
|
2896
|
+
if (e.key !== "Enter") return;
|
|
2897
|
+
e.preventDefault();
|
|
2898
|
+
commit();
|
|
2899
|
+
});
|
|
2900
|
+
}
|
|
2901
|
+
frame.body.append(el("div", "kit-gallery-layout", el("div", "kit-gallery-shelves", ...shelves), panel));
|
|
2902
|
+
frame.actions.append(cancel, primary);
|
|
2903
|
+
dialog.addEventListener("click", (e) => {
|
|
2904
|
+
if (e.target === dialog) frame.close();
|
|
2905
|
+
});
|
|
2906
|
+
choose(chosen.item.id);
|
|
2907
|
+
frame.open();
|
|
2908
|
+
if (nameInput && chosen.section.usesDetails !== false) nameInput.focus();
|
|
2909
|
+
else tiles.get(chosen.item.id)?.focus();
|
|
2910
|
+
return { dialog, close: () => frame.close() };
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2766
2913
|
// src/link-status.ts
|
|
2767
2914
|
function linkStatusClass(s) {
|
|
2768
2915
|
if (s.state === "off" || s.state === "error") return "off";
|
|
@@ -3161,6 +3308,7 @@ exports.openAnchoredPanel = openAnchoredPanel;
|
|
|
3161
3308
|
exports.openComments = openComments;
|
|
3162
3309
|
exports.openContextMenu = openContextMenu;
|
|
3163
3310
|
exports.openGameIdEditor = openGameIdEditor;
|
|
3311
|
+
exports.openKitGallery = openKitGallery;
|
|
3164
3312
|
exports.openNotesEditor = openNotesEditor;
|
|
3165
3313
|
exports.openPopover = openPopover;
|
|
3166
3314
|
exports.paintVcBadges = paintVcBadges;
|