@wildwinter/app-shell 0.37.0 → 0.39.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/LICENSES.md +62 -0
- package/README.md +21 -0
- package/dist/about.css +13 -34
- package/dist/about.css.map +1 -1
- package/dist/anchored.css +5 -5
- package/dist/anchored.css.map +1 -1
- package/dist/app-store.cjs +15 -0
- package/dist/app-store.cjs.map +1 -1
- package/dist/app-store.d.cts +25 -1
- package/dist/app-store.d.ts +25 -1
- package/dist/app-store.js +14 -1
- package/dist/app-store.js.map +1 -1
- package/dist/chunk-2ECJUTSX.js +97 -0
- package/dist/chunk-2ECJUTSX.js.map +1 -0
- package/dist/chunk-2NMVIM54.js +55 -0
- package/dist/chunk-2NMVIM54.js.map +1 -0
- package/dist/chunk-C6UVQYKI.js +70 -0
- package/dist/chunk-C6UVQYKI.js.map +1 -0
- package/dist/chunk-IU7EY6BI.js +26 -0
- package/dist/chunk-IU7EY6BI.js.map +1 -0
- package/dist/chunk-K2AOLQW4.js +82 -0
- package/dist/chunk-K2AOLQW4.js.map +1 -0
- package/dist/chunk-KGAMP5LW.js +87 -0
- package/dist/chunk-KGAMP5LW.js.map +1 -0
- package/dist/chunk-L5HOBEKL.js +534 -0
- package/dist/chunk-L5HOBEKL.js.map +1 -0
- package/dist/chunk-P4G4ERG6.js +60 -0
- package/dist/chunk-P4G4ERG6.js.map +1 -0
- package/dist/chunk-P6WLAEKZ.js +71 -0
- package/dist/chunk-P6WLAEKZ.js.map +1 -0
- package/dist/chunk-S4KWQLYN.js +66 -0
- package/dist/chunk-S4KWQLYN.js.map +1 -0
- package/dist/chunk-XZYZXY7I.js +554 -0
- package/dist/chunk-XZYZXY7I.js.map +1 -0
- package/dist/comments.css +5 -3
- package/dist/comments.css.map +1 -1
- package/dist/confirm.css +1 -54
- package/dist/confirm.css.map +1 -1
- package/dist/context-menu.cjs +250 -0
- package/dist/context-menu.cjs.map +1 -0
- package/dist/context-menu.css +64 -0
- package/dist/context-menu.css.map +1 -0
- package/dist/context-menu.d.cts +25 -0
- package/dist/context-menu.d.ts +25 -0
- package/dist/context-menu.js +5 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/controls.css +155 -0
- package/dist/controls.css.map +1 -0
- package/dist/dialog.cjs +222 -0
- package/dist/dialog.cjs.map +1 -0
- package/dist/dialog.css +55 -0
- package/dist/dialog.css.map +1 -0
- package/dist/dialog.d.cts +28 -0
- package/dist/dialog.d.ts +28 -0
- package/dist/dialog.js +5 -0
- package/dist/dialog.js.map +1 -0
- package/dist/floating.cjs +83 -0
- package/dist/floating.cjs.map +1 -0
- package/dist/floating.d.cts +25 -0
- package/dist/floating.d.ts +25 -0
- package/dist/floating.js +4 -0
- package/dist/floating.js.map +1 -0
- package/dist/identity.css +15 -50
- package/dist/identity.css.map +1 -1
- package/dist/index.cjs +1322 -258
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +349 -131
- package/dist/index.d.ts +349 -131
- package/dist/index.js +259 -808
- package/dist/index.js.map +1 -1
- package/dist/job.css +23 -0
- package/dist/job.css.map +1 -1
- package/dist/link-status.cjs +430 -0
- package/dist/link-status.cjs.map +1 -0
- package/dist/link-status.css +76 -0
- package/dist/link-status.css.map +1 -0
- package/dist/link-status.d.cts +53 -0
- package/dist/link-status.d.ts +53 -0
- package/dist/link-status.js +5 -0
- package/dist/link-status.js.map +1 -0
- package/dist/menu.cjs +62 -1
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.d.cts +88 -1
- package/dist/menu.d.ts +88 -1
- package/dist/menu.js +1 -1
- package/dist/notes-editor.css +3 -46
- package/dist/notes-editor.css.map +1 -1
- package/dist/pane-shell.css +16 -3
- package/dist/pane-shell.css.map +1 -1
- package/dist/property-list-D3VZCJzi.d.cts +162 -0
- package/dist/property-list-D3VZCJzi.d.ts +162 -0
- package/dist/property-list.cjs +784 -0
- package/dist/property-list.cjs.map +1 -0
- package/dist/property-list.d.cts +1 -0
- package/dist/property-list.d.ts +1 -0
- package/dist/property-list.js +4 -0
- package/dist/property-list.js.map +1 -0
- package/dist/settings.css +63 -8
- package/dist/settings.css.map +1 -1
- package/dist/stale.css +3 -0
- package/dist/stale.css.map +1 -1
- package/dist/stepper.css +35 -0
- package/dist/stepper.css.map +1 -1
- package/dist/tokens.css +19 -0
- package/dist/tokens.css.map +1 -1
- package/dist/tool-window.cjs +63 -0
- package/dist/tool-window.cjs.map +1 -1
- package/dist/tool-window.css +6 -3
- package/dist/tool-window.css.map +1 -1
- package/dist/tool-window.d.cts +67 -1
- package/dist/tool-window.d.ts +67 -1
- package/dist/tool-window.js +63 -1
- package/dist/tool-window.js.map +1 -1
- package/dist/updater-view.cjs +283 -0
- package/dist/updater-view.cjs.map +1 -0
- package/dist/updater-view.d.cts +23 -0
- package/dist/updater-view.d.ts +23 -0
- package/dist/updater-view.js +6 -0
- package/dist/updater-view.js.map +1 -0
- package/dist/updater.cjs +12 -16
- package/dist/updater.cjs.map +1 -1
- package/dist/updater.css +44 -0
- package/dist/updater.css.map +1 -0
- package/dist/updater.js +12 -16
- package/dist/updater.js.map +1 -1
- package/dist/util.cjs +78 -0
- package/dist/util.cjs.map +1 -0
- package/dist/util.d.cts +37 -0
- package/dist/util.d.ts +37 -0
- package/dist/util.js +3 -0
- package/dist/util.js.map +1 -0
- package/dist/vc.css +3 -2
- package/dist/vc.css.map +1 -1
- package/dist/welcome.cjs +215 -0
- package/dist/welcome.cjs.map +1 -0
- package/dist/welcome.css +112 -0
- package/dist/welcome.css.map +1 -0
- package/dist/welcome.d.cts +55 -0
- package/dist/welcome.d.ts +55 -0
- package/dist/welcome.js +4 -0
- package/dist/welcome.js.map +1 -0
- package/package.json +58 -2
- package/dist/chunk-QDPFU4WX.js +0 -43
- package/dist/chunk-QDPFU4WX.js.map +0 -1
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
// src/tooltip.ts
|
|
2
|
+
var B_OPEN = "";
|
|
3
|
+
var B_CLOSE = "";
|
|
4
|
+
function tipBold(s) {
|
|
5
|
+
return `${B_OPEN}${s}${B_CLOSE}`;
|
|
6
|
+
}
|
|
7
|
+
function renderTip(host, text) {
|
|
8
|
+
host.textContent = "";
|
|
9
|
+
const re = /\u0002([^\u0003]*)\u0003/g;
|
|
10
|
+
let last = 0;
|
|
11
|
+
let m;
|
|
12
|
+
while ((m = re.exec(text)) !== null) {
|
|
13
|
+
if (m.index > last) host.append(text.slice(last, m.index));
|
|
14
|
+
const strong = document.createElement("strong");
|
|
15
|
+
strong.textContent = m[1] ?? "";
|
|
16
|
+
host.append(strong);
|
|
17
|
+
last = m.index + m[0].length;
|
|
18
|
+
}
|
|
19
|
+
if (last < text.length) host.append(text.slice(last));
|
|
20
|
+
}
|
|
21
|
+
var inited = false;
|
|
22
|
+
var checked = false;
|
|
23
|
+
var suppressed;
|
|
24
|
+
var SHOW_DELAY = 350;
|
|
25
|
+
var EDGE = 6;
|
|
26
|
+
var GAP = 7;
|
|
27
|
+
var tip = null;
|
|
28
|
+
var timer = 0;
|
|
29
|
+
var active = null;
|
|
30
|
+
var activeKey = null;
|
|
31
|
+
function ensureEl() {
|
|
32
|
+
if (tip) return tip;
|
|
33
|
+
const el2 = document.createElement("div");
|
|
34
|
+
el2.className = "tooltip";
|
|
35
|
+
el2.setAttribute("role", "tooltip");
|
|
36
|
+
el2.hidden = true;
|
|
37
|
+
document.body.appendChild(el2);
|
|
38
|
+
tip = el2;
|
|
39
|
+
return el2;
|
|
40
|
+
}
|
|
41
|
+
var rectOf = (anchor) => anchor instanceof HTMLElement ? anchor.getBoundingClientRect() : anchor;
|
|
42
|
+
function place(anchor) {
|
|
43
|
+
const t = ensureEl();
|
|
44
|
+
const r = rectOf(anchor);
|
|
45
|
+
const tr = t.getBoundingClientRect();
|
|
46
|
+
let top = r.top - tr.height - GAP;
|
|
47
|
+
if (top < EDGE) top = r.top + r.height + GAP;
|
|
48
|
+
let left = r.left + r.width / 2 - tr.width / 2;
|
|
49
|
+
left = Math.max(EDGE, Math.min(left, window.innerWidth - tr.width - EDGE));
|
|
50
|
+
t.style.left = `${Math.round(left)}px`;
|
|
51
|
+
t.style.top = `${Math.round(top)}px`;
|
|
52
|
+
}
|
|
53
|
+
function show(anchor) {
|
|
54
|
+
const text = anchor.dataset["tip"];
|
|
55
|
+
if (!text) return;
|
|
56
|
+
paint(anchor, text);
|
|
57
|
+
}
|
|
58
|
+
function paint(anchor, text) {
|
|
59
|
+
if (suppressed?.()) return;
|
|
60
|
+
const t = ensureEl();
|
|
61
|
+
const host = (anchor instanceof HTMLElement ? anchor.closest("dialog[open]") : null) ?? document.body;
|
|
62
|
+
if (t.parentElement !== host) host.appendChild(t);
|
|
63
|
+
active = anchor instanceof HTMLElement ? anchor : null;
|
|
64
|
+
renderTip(t, text);
|
|
65
|
+
t.hidden = false;
|
|
66
|
+
t.classList.remove("show");
|
|
67
|
+
void t.offsetWidth;
|
|
68
|
+
place(anchor);
|
|
69
|
+
t.classList.add("show");
|
|
70
|
+
}
|
|
71
|
+
function hide() {
|
|
72
|
+
if (timer) {
|
|
73
|
+
window.clearTimeout(timer);
|
|
74
|
+
timer = 0;
|
|
75
|
+
}
|
|
76
|
+
active = null;
|
|
77
|
+
activeKey = null;
|
|
78
|
+
if (tip) {
|
|
79
|
+
tip.hidden = true;
|
|
80
|
+
tip.classList.remove("show");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function schedule(anchor) {
|
|
84
|
+
if (anchor === active) return;
|
|
85
|
+
if (timer) window.clearTimeout(timer);
|
|
86
|
+
timer = window.setTimeout(() => show(anchor), SHOW_DELAY);
|
|
87
|
+
}
|
|
88
|
+
function tipAt(key, rect, text) {
|
|
89
|
+
if (key === activeKey) {
|
|
90
|
+
if (tip && !tip.hidden) {
|
|
91
|
+
renderTip(tip, text);
|
|
92
|
+
place(rect);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
hide();
|
|
97
|
+
activeKey = key;
|
|
98
|
+
timer = window.setTimeout(() => {
|
|
99
|
+
timer = 0;
|
|
100
|
+
paint(rect, text);
|
|
101
|
+
}, SHOW_DELAY);
|
|
102
|
+
}
|
|
103
|
+
function hideTip() {
|
|
104
|
+
hide();
|
|
105
|
+
}
|
|
106
|
+
function ensureTooltipHost() {
|
|
107
|
+
initTooltips();
|
|
108
|
+
}
|
|
109
|
+
function checkTooltipHost() {
|
|
110
|
+
if (checked) return;
|
|
111
|
+
checked = true;
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
if (inited || typeof document === "undefined") return;
|
|
114
|
+
if (document.querySelector("[data-tip]")) {
|
|
115
|
+
console.warn("app-shell: something set `data-tip` but no tooltip host is mounted, so those rollovers will not draw. Call initTooltips() once per window.");
|
|
116
|
+
}
|
|
117
|
+
}, 0);
|
|
118
|
+
}
|
|
119
|
+
var tipAncestor = (n) => n instanceof Element ? n.closest("[data-tip]") : null;
|
|
120
|
+
function initTooltips(opts = {}) {
|
|
121
|
+
if (opts.suppressed !== void 0) suppressed = opts.suppressed;
|
|
122
|
+
if (inited) return;
|
|
123
|
+
inited = true;
|
|
124
|
+
document.addEventListener("pointerover", (e) => {
|
|
125
|
+
const el2 = tipAncestor(e.target);
|
|
126
|
+
if (el2) schedule(el2);
|
|
127
|
+
});
|
|
128
|
+
document.addEventListener("pointerout", (e) => {
|
|
129
|
+
const el2 = tipAncestor(e.target);
|
|
130
|
+
if (!el2) return;
|
|
131
|
+
const to = e.relatedTarget;
|
|
132
|
+
if (to instanceof Node && el2.contains(to)) return;
|
|
133
|
+
hide();
|
|
134
|
+
});
|
|
135
|
+
document.addEventListener("focusin", (e) => {
|
|
136
|
+
const el2 = tipAncestor(e.target);
|
|
137
|
+
if (el2) schedule(el2);
|
|
138
|
+
});
|
|
139
|
+
document.addEventListener("focusout", () => hide());
|
|
140
|
+
document.addEventListener("pointerdown", () => hide(), true);
|
|
141
|
+
document.addEventListener("scroll", () => {
|
|
142
|
+
if (active) hide();
|
|
143
|
+
}, true);
|
|
144
|
+
document.addEventListener("keydown", (e) => {
|
|
145
|
+
if (e.key === "Escape") hide();
|
|
146
|
+
});
|
|
147
|
+
window.addEventListener("blur", () => hide());
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/icons.ts
|
|
151
|
+
var icon = {
|
|
152
|
+
// --- dismissing and revealing ---------------------------------------------
|
|
153
|
+
/** Close a panel, a dialog, a popover. Patterpad's, twelve times over. */
|
|
154
|
+
close: "\u2715",
|
|
155
|
+
/** The overflow menu on a document or a row: "more about this". */
|
|
156
|
+
more: "\u22EF",
|
|
157
|
+
/** Collapsed disclosure, pointing at what would open. */
|
|
158
|
+
collapsed: "\u25B8",
|
|
159
|
+
/** Expanded disclosure. */
|
|
160
|
+
expanded: "\u25BE",
|
|
161
|
+
/** A dropdown's affordance, where it is not a real <select>. */
|
|
162
|
+
dropdown: "\u25BE",
|
|
163
|
+
// --- moving through things ------------------------------------------------
|
|
164
|
+
/** Back / previous, in a breadcrumb or a stepper. */
|
|
165
|
+
back: "\u2039",
|
|
166
|
+
/** Forward / next. */
|
|
167
|
+
forward: "\u203A",
|
|
168
|
+
/** Up one, in a list. */
|
|
169
|
+
up: "\u2191",
|
|
170
|
+
/** Down one. */
|
|
171
|
+
down: "\u2193",
|
|
172
|
+
// --- state ----------------------------------------------------------------
|
|
173
|
+
/** Done, applied, agreed. */
|
|
174
|
+
tick: "\u2713",
|
|
175
|
+
/** Somebody else holds this: the version-control lock. */
|
|
176
|
+
locked: "\u2298",
|
|
177
|
+
/** Read-only on disk with no other holder: the resting state of everything
|
|
178
|
+
* in a lock-based working copy that nobody has checked out yet. */
|
|
179
|
+
readOnly: "\u25CB",
|
|
180
|
+
/** YOU hold this one: checked out / opened by the current user, still yours to
|
|
181
|
+
* edit. Shares its glyph with `note`, which the table permits: an entry is a
|
|
182
|
+
* MEANING, and two meanings may draw the same shape. */
|
|
183
|
+
checkedOut: "\u270E",
|
|
184
|
+
/** Tracked, with local changes not yet committed. */
|
|
185
|
+
modified: "\u25CF",
|
|
186
|
+
/** Not in version control yet: new since the last commit. */
|
|
187
|
+
untracked: "+",
|
|
188
|
+
/** Something needs attention but is not fatal. */
|
|
189
|
+
warning: "\u203C",
|
|
190
|
+
/** A live thing: the running position, an active marker. */
|
|
191
|
+
dot: "\u25CF",
|
|
192
|
+
/** Play, in the sense of "run this". */
|
|
193
|
+
play: "\u25B6",
|
|
194
|
+
/** Start the thing again from the top: a play session, a sweep. Named for the
|
|
195
|
+
* act, not the arrow, which is the table's rule. */
|
|
196
|
+
restart: "\u27F2",
|
|
197
|
+
/** The three ways a collection can be shown. Named by what you get rather than
|
|
198
|
+
* by the glyph, so a second app can pick the same three without copying
|
|
199
|
+
* somebody's taste in symbols. */
|
|
200
|
+
viewCards: "\u25A6",
|
|
201
|
+
viewTable: "\u2630",
|
|
202
|
+
viewNode: "\u25C8",
|
|
203
|
+
// --- handling -------------------------------------------------------------
|
|
204
|
+
/** The drag grip on a reorderable row. */
|
|
205
|
+
grip: "\u283F",
|
|
206
|
+
/** Add one of whatever this list holds. */
|
|
207
|
+
add: "+",
|
|
208
|
+
// --- annotation -----------------------------------------------------------
|
|
209
|
+
/** Documentation notes: the pencil. Both apps had chosen it independently,
|
|
210
|
+
* which is the happiest way for a vocabulary entry to arrive. */
|
|
211
|
+
note: "\u270E",
|
|
212
|
+
/** A comment thread. Speech, not a pencil: documentation states the reason,
|
|
213
|
+
* comments are the conversation, and the two must never look alike. */
|
|
214
|
+
comment: "\u275D"
|
|
215
|
+
};
|
|
216
|
+
var STROKE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.571" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">';
|
|
217
|
+
var FILL = '<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">';
|
|
218
|
+
var stroked = (inner) => `${STROKE}${inner}</svg>`;
|
|
219
|
+
var filled = (inner) => `${FILL}${inner}</svg>`;
|
|
220
|
+
var DISC = filled('<circle cx="12" cy="12" r="6"/>');
|
|
221
|
+
var DISC_LARGE = filled('<circle cx="12" cy="12" r="9"/>');
|
|
222
|
+
var DRAWN = {
|
|
223
|
+
// --- dismissing and revealing ---------------------------------------------
|
|
224
|
+
/** Close a panel, a dialog, a popover. (x) */
|
|
225
|
+
close: stroked('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>'),
|
|
226
|
+
/** The overflow menu on a document or a row: "more about this". (ellipsis) */
|
|
227
|
+
more: stroked('<circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/>'),
|
|
228
|
+
/** Collapsed disclosure, pointing at what would open. (chevron-right) */
|
|
229
|
+
collapsed: stroked('<path d="m9 18 6-6-6-6"/>'),
|
|
230
|
+
/** Expanded disclosure. (chevron-down) */
|
|
231
|
+
expanded: stroked('<path d="m6 9 6 6 6-6"/>'),
|
|
232
|
+
/** A dropdown's affordance, where it is not a real <select>. (chevron-down) */
|
|
233
|
+
dropdown: stroked('<path d="m6 9 6 6 6-6"/>'),
|
|
234
|
+
// --- moving through things ------------------------------------------------
|
|
235
|
+
/** Back / previous, in a breadcrumb or a stepper. (chevron-left) */
|
|
236
|
+
back: stroked('<path d="m15 18-6-6 6-6"/>'),
|
|
237
|
+
/** Forward / next. (chevron-right) */
|
|
238
|
+
forward: stroked('<path d="m9 18 6-6-6-6"/>'),
|
|
239
|
+
/** Up one, in a list. (arrow-up) */
|
|
240
|
+
up: stroked('<path d="m5 12 7-7 7 7"/><path d="M12 19V5"/>'),
|
|
241
|
+
/** Down one. (arrow-down) */
|
|
242
|
+
down: stroked('<path d="M12 5v14"/><path d="m19 12-7 7-7-7"/>'),
|
|
243
|
+
/** History back. (arrow-left) */
|
|
244
|
+
arrowLeft: stroked('<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>'),
|
|
245
|
+
/** History forward; "go there". (arrow-right) */
|
|
246
|
+
arrowRight: stroked('<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>'),
|
|
247
|
+
// --- state ----------------------------------------------------------------
|
|
248
|
+
/** Done, applied, agreed. (check) */
|
|
249
|
+
tick: stroked('<path d="M20 6 9 17l-5-5"/>'),
|
|
250
|
+
/** Somebody else holds this: the version-control lock. (lock) */
|
|
251
|
+
locked: stroked('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>'),
|
|
252
|
+
/** Read-only on disk with no other holder. (lock-open) An open lock rather
|
|
253
|
+
* than a struck-out eye: this state is not a prohibition. Nobody holds the
|
|
254
|
+
* file, saving checks it out, and it is the resting state of everything the
|
|
255
|
+
* author has not touched yet under a lock-based VCS. eye-off would say "you
|
|
256
|
+
* cannot", which is false here; the open lock says "not held", beside
|
|
257
|
+
* `locked`, which is the shut one, so the two read as a pair. */
|
|
258
|
+
readOnly: stroked('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 9.9-1"/>'),
|
|
259
|
+
/** YOU hold this one: checked out, still yours to edit. (pencil) */
|
|
260
|
+
checkedOut: stroked('<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/>'),
|
|
261
|
+
/** Tracked, with local changes not yet committed. (a disc; see DISC) */
|
|
262
|
+
modified: DISC,
|
|
263
|
+
/** Not in version control yet: new since the last commit. (plus) */
|
|
264
|
+
untracked: stroked('<path d="M5 12h14"/><path d="M12 5v14"/>'),
|
|
265
|
+
/** Something needs attention but is not fatal. (triangle-alert) */
|
|
266
|
+
warning: stroked('<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/>'),
|
|
267
|
+
/** A live thing: the running position, an active marker. (a disc) */
|
|
268
|
+
dot: DISC,
|
|
269
|
+
/** Play, in the sense of "run this". (play) */
|
|
270
|
+
play: stroked('<path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"/>'),
|
|
271
|
+
/** Start the thing again from the top: a play session, a sweep. (rotate-ccw) */
|
|
272
|
+
restart: stroked('<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>'),
|
|
273
|
+
/** The three ways a collection can be shown, named by what you get. */
|
|
274
|
+
/** Cards. (layout-grid) */
|
|
275
|
+
viewCards: stroked('<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>'),
|
|
276
|
+
/** A table. (rows-3: a ruled box, which is a table. `list` is bullets, and
|
|
277
|
+
* the view is not a list.) */
|
|
278
|
+
viewTable: stroked('<rect width="18" height="18" x="3" y="3" rx="2"/><path d="M21 9H3"/><path d="M21 15H3"/>'),
|
|
279
|
+
/** A node graph. (waypoints: four nodes on edges reads as a graph.
|
|
280
|
+
* `git-fork` reads as version control, which this family also draws, and
|
|
281
|
+
* a picture that means two things is the fault this table exists to
|
|
282
|
+
* prevent.) */
|
|
283
|
+
viewNode: stroked('<path d="m10.586 5.414-5.172 5.172"/><path d="m18.586 13.414-5.172 5.172"/><path d="M6 12h12"/><circle cx="12" cy="20" r="2"/><circle cx="12" cy="4" r="2"/><circle cx="20" cy="12" r="2"/><circle cx="4" cy="12" r="2"/>'),
|
|
284
|
+
/** Record: the disc, in whatever colour the button is. (a disc; see DISC_LARGE) */
|
|
285
|
+
record: DISC_LARGE,
|
|
286
|
+
// --- handling -------------------------------------------------------------
|
|
287
|
+
/** The drag grip on a reorderable row. (grip-vertical) */
|
|
288
|
+
grip: stroked('<circle cx="9" cy="12" r="1"/><circle cx="9" cy="5" r="1"/><circle cx="9" cy="19" r="1"/><circle cx="15" cy="12" r="1"/><circle cx="15" cy="5" r="1"/><circle cx="15" cy="19" r="1"/>'),
|
|
289
|
+
/** Add one of whatever this list holds. (plus) */
|
|
290
|
+
add: stroked('<path d="M5 12h14"/><path d="M12 5v14"/>'),
|
|
291
|
+
/** Connect: to a server, a live link, a running game. (plug) */
|
|
292
|
+
connect: stroked('<path d="M12 22v-5"/><path d="M15 8V2"/><path d="M17 8a1 1 0 0 1 1 1v4a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1z"/><path d="M9 8V2"/>'),
|
|
293
|
+
/** Search. (search) */
|
|
294
|
+
search: stroked('<path d="m21 21-4.34-4.34"/><circle cx="11" cy="11" r="8"/>'),
|
|
295
|
+
/** Keep this window on top. (pin) */
|
|
296
|
+
pin: stroked('<path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/>'),
|
|
297
|
+
/** Settings. (settings) */
|
|
298
|
+
settings: stroked('<path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915"/><circle cx="12" cy="12" r="3"/>'),
|
|
299
|
+
// --- annotation -----------------------------------------------------------
|
|
300
|
+
/** Documentation notes: a document with lines on it. (file-text) The glyph
|
|
301
|
+
* table drew a pencil and shared it with `checkedOut`; the drawn set gives
|
|
302
|
+
* the two meanings two shapes, and notes get the document, which is what
|
|
303
|
+
* the shell's own noteFilled/noteOutline pair had always drawn. */
|
|
304
|
+
note: stroked('<path d="M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z"/><path d="M14 2v5a1 1 0 0 0 1 1h5"/><path d="M10 9H8"/><path d="M16 13H8"/><path d="M16 17H8"/>'),
|
|
305
|
+
/** A comment thread. Speech, not a document: documentation states the
|
|
306
|
+
* reason, comments are the conversation, and the two must never look
|
|
307
|
+
* alike. (message-square) */
|
|
308
|
+
comment: stroked('<path d="M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z"/>')
|
|
309
|
+
};
|
|
310
|
+
var iconSvg = {
|
|
311
|
+
...DRAWN,
|
|
312
|
+
/** A document with lines: notes exist on this thing. (legacy, 16 grid) */
|
|
313
|
+
noteFilled: '<svg viewBox="0 0 16 16" width="13" height="13" fill="currentColor" fill-rule="evenodd" aria-hidden="true"><path d="M3.4 1.4h5.3L12.6 5.3v8.1a1.2 1.2 0 0 1-1.2 1.2H3.4a1.2 1.2 0 0 1-1.2-1.2V2.6A1.2 1.2 0 0 1 3.4 1.4ZM4.9 6.8h6.2v1.1H4.9Zm0 2.1h6.2v1.1H4.9Zm0 2.1h3.7v1.1H4.9Z"/></svg>',
|
|
314
|
+
/** The same document, empty: nothing written here yet. (legacy, 16 grid) */
|
|
315
|
+
noteOutline: '<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" stroke-width="1.1" stroke-linejoin="round" stroke-linecap="round" aria-hidden="true"><path d="M3.4 2h4.9l3.9 3.9v7.5a1 1 0 0 1-1 1H3.4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z"/><path d="M8.3 2.2v3.8h3.8"/><path d="M4.9 8h6.2M4.9 10h6.2M4.9 12h3.7" stroke-width="0.95"/></svg>'
|
|
316
|
+
};
|
|
317
|
+
var ICON_NAMES = Object.keys(DRAWN);
|
|
318
|
+
var ICON_SIZE = 14;
|
|
319
|
+
function iconHtml(name, size = ICON_SIZE) {
|
|
320
|
+
return DRAWN[name].replace("<svg ", `<svg width="${size}" height="${size}" data-icon="${name}" `);
|
|
321
|
+
}
|
|
322
|
+
var templates = /* @__PURE__ */ new Map();
|
|
323
|
+
function iconNode(name, size = ICON_SIZE) {
|
|
324
|
+
let tpl = templates.get(name);
|
|
325
|
+
if (!tpl) {
|
|
326
|
+
const holder = document.createElement("template");
|
|
327
|
+
holder.innerHTML = DRAWN[name];
|
|
328
|
+
tpl = holder.content.firstElementChild;
|
|
329
|
+
tpl.setAttribute("data-icon", name);
|
|
330
|
+
templates.set(name, tpl);
|
|
331
|
+
}
|
|
332
|
+
const node = tpl.cloneNode(true);
|
|
333
|
+
node.setAttribute("width", String(size));
|
|
334
|
+
node.setAttribute("height", String(size));
|
|
335
|
+
return node;
|
|
336
|
+
}
|
|
337
|
+
var BY_GLYPH = /* @__PURE__ */ new Map();
|
|
338
|
+
for (const [name, glyph] of Object.entries(icon)) {
|
|
339
|
+
if (!BY_GLYPH.has(glyph)) BY_GLYPH.set(glyph, name);
|
|
340
|
+
}
|
|
341
|
+
function iconNameOfGlyph(glyph) {
|
|
342
|
+
return BY_GLYPH.get(glyph);
|
|
343
|
+
}
|
|
344
|
+
function isIconName(s) {
|
|
345
|
+
return Object.prototype.hasOwnProperty.call(DRAWN, s);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// src/dom.ts
|
|
349
|
+
function el(tag, classNameOrProps, ...children) {
|
|
350
|
+
const node = document.createElement(tag);
|
|
351
|
+
const props = typeof classNameOrProps === "string" ? { className: classNameOrProps } : classNameOrProps ?? {};
|
|
352
|
+
if (props.className) node.className = props.className;
|
|
353
|
+
if (props.text !== void 0 && props.text !== null) node.textContent = props.text;
|
|
354
|
+
if (props.title !== void 0) node.title = props.title;
|
|
355
|
+
if (props.tip !== void 0) {
|
|
356
|
+
node.dataset["tip"] = props.tip;
|
|
357
|
+
node.setAttribute("aria-label", props.tip);
|
|
358
|
+
ensureTooltipHost();
|
|
359
|
+
}
|
|
360
|
+
if (props.onClick) node.addEventListener("click", props.onClick);
|
|
361
|
+
for (const child of children) {
|
|
362
|
+
if (child === null || child === void 0) continue;
|
|
363
|
+
node.append(child);
|
|
364
|
+
}
|
|
365
|
+
checkTooltipHost();
|
|
366
|
+
return node;
|
|
367
|
+
}
|
|
368
|
+
function iconBtn(name, title, onClick, disabled = false, danger = false) {
|
|
369
|
+
const b = el("button", `shell-icon${danger ? " danger" : ""}`);
|
|
370
|
+
b.type = "button";
|
|
371
|
+
b.dataset["tip"] = title;
|
|
372
|
+
b.setAttribute("aria-label", title);
|
|
373
|
+
const word = isIconName(name) ? name : iconNameOfGlyph(name);
|
|
374
|
+
if (word) b.append(iconNode(word));
|
|
375
|
+
else b.textContent = name;
|
|
376
|
+
b.disabled = disabled;
|
|
377
|
+
b.addEventListener("click", onClick);
|
|
378
|
+
return b;
|
|
379
|
+
}
|
|
380
|
+
function labelled(label, control) {
|
|
381
|
+
const target = control.matches("input, select, textarea") ? control : control.querySelector("input:not([type=button]):not([type=submit]), select, textarea");
|
|
382
|
+
const w = el(target ? "label" : "div", "shell-labelled");
|
|
383
|
+
w.append(el("span", "shell-fieldcap", label), control);
|
|
384
|
+
if (target) {
|
|
385
|
+
if (!target.id) target.id = `shell-f-${Math.random().toString(36).slice(2, 9)}`;
|
|
386
|
+
w.htmlFor = target.id;
|
|
387
|
+
}
|
|
388
|
+
return w;
|
|
389
|
+
}
|
|
390
|
+
function moveItem(arr, i, delta) {
|
|
391
|
+
const j = i + delta;
|
|
392
|
+
if (j < 0 || j >= arr.length) return false;
|
|
393
|
+
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
var CHIP_ICON = 10;
|
|
397
|
+
function tagChips(holder, onChange) {
|
|
398
|
+
const wrap = el("div", "shell-tags");
|
|
399
|
+
const input = el("input", "shell-tag-input");
|
|
400
|
+
input.type = "text";
|
|
401
|
+
input.placeholder = "Add value";
|
|
402
|
+
input.spellcheck = false;
|
|
403
|
+
const makeChip = (v) => {
|
|
404
|
+
const chip = el("span", "shell-tag", v);
|
|
405
|
+
const x = el("button", "shell-tag-x", iconNode("close", CHIP_ICON));
|
|
406
|
+
x.type = "button";
|
|
407
|
+
x.dataset["tip"] = `Remove ${v}`;
|
|
408
|
+
x.setAttribute("aria-label", `Remove ${v}`);
|
|
409
|
+
x.addEventListener("click", () => {
|
|
410
|
+
holder.values = (holder.values ?? []).filter((o) => o !== v);
|
|
411
|
+
chip.remove();
|
|
412
|
+
onChange?.();
|
|
413
|
+
});
|
|
414
|
+
chip.append(x);
|
|
415
|
+
return chip;
|
|
416
|
+
};
|
|
417
|
+
const commit = () => {
|
|
418
|
+
const v = input.value.trim();
|
|
419
|
+
if (v && !(holder.values ?? []).includes(v)) {
|
|
420
|
+
(holder.values ??= []).push(v);
|
|
421
|
+
wrap.insertBefore(makeChip(v), input);
|
|
422
|
+
onChange?.();
|
|
423
|
+
}
|
|
424
|
+
input.value = "";
|
|
425
|
+
};
|
|
426
|
+
input.addEventListener("keydown", (e) => {
|
|
427
|
+
if (e.key === "Enter" || e.key === ",") {
|
|
428
|
+
e.preventDefault();
|
|
429
|
+
commit();
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
input.addEventListener("blur", commit);
|
|
433
|
+
for (const v of holder.values ?? []) wrap.append(makeChip(v));
|
|
434
|
+
wrap.append(input);
|
|
435
|
+
return wrap;
|
|
436
|
+
}
|
|
437
|
+
function stageChips(holder, onChange) {
|
|
438
|
+
const wrap = el("div", "shell-tags shell-stages");
|
|
439
|
+
const input = el("input", "shell-tag-input");
|
|
440
|
+
input.type = "text";
|
|
441
|
+
input.placeholder = "Add stage";
|
|
442
|
+
input.spellcheck = false;
|
|
443
|
+
const control = (name, tip2, disabled, onClick) => {
|
|
444
|
+
const b = el("button", "shell-tag-x shell-tag-move", iconNode(name, CHIP_ICON));
|
|
445
|
+
b.type = "button";
|
|
446
|
+
b.dataset["tip"] = tip2;
|
|
447
|
+
b.setAttribute("aria-label", tip2);
|
|
448
|
+
b.disabled = disabled;
|
|
449
|
+
b.addEventListener("click", onClick);
|
|
450
|
+
return b;
|
|
451
|
+
};
|
|
452
|
+
const rebuild = () => {
|
|
453
|
+
for (const c of Array.from(wrap.children)) if (c !== input) c.remove();
|
|
454
|
+
const stages = holder.stages ?? [];
|
|
455
|
+
stages.forEach((v, i) => {
|
|
456
|
+
const chip = el("span", "shell-tag", `${i + 1}. ${v}`);
|
|
457
|
+
chip.dataset["stage"] = v;
|
|
458
|
+
chip.append(
|
|
459
|
+
control(
|
|
460
|
+
"back",
|
|
461
|
+
`Move ${v} earlier`,
|
|
462
|
+
i === 0,
|
|
463
|
+
() => {
|
|
464
|
+
if (moveItem(stages, i, -1)) {
|
|
465
|
+
rebuild();
|
|
466
|
+
onChange?.();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
),
|
|
470
|
+
control(
|
|
471
|
+
"forward",
|
|
472
|
+
`Move ${v} later`,
|
|
473
|
+
i === stages.length - 1,
|
|
474
|
+
() => {
|
|
475
|
+
if (moveItem(stages, i, 1)) {
|
|
476
|
+
rebuild();
|
|
477
|
+
onChange?.();
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
)
|
|
481
|
+
);
|
|
482
|
+
const x = el("button", "shell-tag-x", iconNode("close", CHIP_ICON));
|
|
483
|
+
x.type = "button";
|
|
484
|
+
x.dataset["tip"] = `Remove ${v}`;
|
|
485
|
+
x.setAttribute("aria-label", `Remove ${v}`);
|
|
486
|
+
x.addEventListener("click", () => {
|
|
487
|
+
holder.stages = (holder.stages ?? []).filter((o) => o !== v);
|
|
488
|
+
rebuild();
|
|
489
|
+
onChange?.();
|
|
490
|
+
});
|
|
491
|
+
chip.append(x);
|
|
492
|
+
wrap.insertBefore(chip, input);
|
|
493
|
+
});
|
|
494
|
+
};
|
|
495
|
+
const commit = () => {
|
|
496
|
+
const v = input.value.trim();
|
|
497
|
+
if (v && !(holder.stages ?? []).includes(v)) {
|
|
498
|
+
(holder.stages ??= []).push(v);
|
|
499
|
+
rebuild();
|
|
500
|
+
onChange?.();
|
|
501
|
+
}
|
|
502
|
+
input.value = "";
|
|
503
|
+
};
|
|
504
|
+
input.addEventListener("keydown", (e) => {
|
|
505
|
+
if (e.key === "Enter" || e.key === ",") {
|
|
506
|
+
e.preventDefault();
|
|
507
|
+
commit();
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
input.addEventListener("blur", commit);
|
|
511
|
+
wrap.append(input);
|
|
512
|
+
rebuild();
|
|
513
|
+
return wrap;
|
|
514
|
+
}
|
|
515
|
+
var reorderDragId = null;
|
|
516
|
+
var clearDropMarks = (host) => host.querySelectorAll(".drop-before, .drop-after").forEach((e) => e.classList.remove("drop-before", "drop-after"));
|
|
517
|
+
function wireReorder(el2, id, axis, onMove) {
|
|
518
|
+
el2.draggable = true;
|
|
519
|
+
el2.dataset["reorderId"] = id;
|
|
520
|
+
const host = () => el2.parentElement ?? el2;
|
|
521
|
+
el2.addEventListener("dragstart", (e) => {
|
|
522
|
+
reorderDragId = id;
|
|
523
|
+
el2.classList.add("dragging");
|
|
524
|
+
if (e.dataTransfer) {
|
|
525
|
+
e.dataTransfer.effectAllowed = "move";
|
|
526
|
+
e.dataTransfer.setData("text/plain", id);
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
el2.addEventListener("dragend", () => {
|
|
530
|
+
reorderDragId = null;
|
|
531
|
+
el2.classList.remove("dragging");
|
|
532
|
+
clearDropMarks(host());
|
|
533
|
+
});
|
|
534
|
+
el2.addEventListener("dragover", (e) => {
|
|
535
|
+
if (!reorderDragId || reorderDragId === id) return;
|
|
536
|
+
e.preventDefault();
|
|
537
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
538
|
+
const r = el2.getBoundingClientRect();
|
|
539
|
+
const before = axis === "y" ? e.clientY < r.top + r.height / 2 : e.clientX < r.left + r.width / 2;
|
|
540
|
+
clearDropMarks(host());
|
|
541
|
+
el2.classList.add(before ? "drop-before" : "drop-after");
|
|
542
|
+
});
|
|
543
|
+
el2.addEventListener("dragleave", () => el2.classList.remove("drop-before", "drop-after"));
|
|
544
|
+
el2.addEventListener("drop", (e) => {
|
|
545
|
+
e.preventDefault();
|
|
546
|
+
const before = el2.classList.contains("drop-before");
|
|
547
|
+
clearDropMarks(host());
|
|
548
|
+
if (reorderDragId && reorderDragId !== id) onMove(reorderDragId, before, id);
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export { ICON_NAMES, ICON_SIZE, el, ensureTooltipHost, hideTip, icon, iconBtn, iconHtml, iconNameOfGlyph, iconNode, iconSvg, initTooltips, isIconName, labelled, moveItem, stageChips, tagChips, tipAt, tipBold, wireReorder };
|
|
553
|
+
//# sourceMappingURL=chunk-XZYZXY7I.js.map
|
|
554
|
+
//# sourceMappingURL=chunk-XZYZXY7I.js.map
|