@gramlot/gramlot-examples 0.3.3 → 0.3.5
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 +6 -3
- package/package.json +4 -3
- package/src/gramlot_examples/catalog.json +54 -0
- package/src/gramlot_examples/gallery/dist/frame.js +548 -36
- package/src/gramlot_examples/gallery/dist/gallery.js +2467 -16677
- package/src/gramlot_examples/gallery/dist/inputs.js +12 -6
- package/src/gramlot_examples/gallery/dist/inspector.js +547 -35
- package/src/gramlot_examples/gallery/dist/layout.js +847 -28
- package/src/gramlot_examples/gallery/dist/notices.json +0 -24
- package/src/gramlot_examples/gallery/dist/theme-styles.js +1 -1
- package/src/gramlot_examples/gallery/gallery-page.js +77 -47
- package/src/gramlot_examples/gallery/gallery.css +61 -38
- package/src/gramlot_examples/gallery/guided-demo.js +151 -0
- package/src/gramlot_examples/gallery/page.js +6 -6
- package/src/gramlot_examples/index.js +1 -0
- package/src/gramlot_examples/pages/layout/01_border.js +80 -0
- package/src/gramlot_examples/pages/layout/01_border.md +23 -0
- package/src/gramlot_examples/pages/layout/02_nested.js +99 -0
- package/src/gramlot_examples/pages/layout/02_nested.md +23 -0
- package/src/gramlot_examples/pages/layout/03_rounded.js +111 -0
- package/src/gramlot_examples/pages/layout/03_rounded.md +25 -0
- package/src/gramlot_examples/pages/layout/04_drawer_handles.js +140 -0
- package/src/gramlot_examples/pages/layout/04_drawer_handles.md +33 -0
- package/src/gramlot_examples/pages/layout/05_nested_lab.js +251 -0
- package/src/gramlot_examples/pages/layout/05_nested_lab.md +25 -0
- package/src/gramlot_examples/pages/layout/06_border_events.js +118 -0
- package/src/gramlot_examples/pages/layout/06_border_events.md +25 -0
- package/src/gramlot_examples/pages/layout/07_tabs.js +300 -0
- package/src/gramlot_examples/pages/layout/07_tabs.md +37 -0
- package/src/gramlot_examples/pages/layout/08_stack.js +142 -0
- package/src/gramlot_examples/pages/layout/08_stack.md +27 -0
- package/src/gramlot_examples/pages/layout/README.md +15 -0
|
@@ -93,6 +93,239 @@
|
|
|
93
93
|
function readParameterEnums(node) {
|
|
94
94
|
return Object.fromEntries(Object.entries(node._getMeta("gramlot_component")?.parameters ?? {}).filter(([, spec]) => spec.enum).map(([name, spec]) => [name, spec.enum]));
|
|
95
95
|
}
|
|
96
|
+
var InspectorHistory = class {
|
|
97
|
+
#undo = [];
|
|
98
|
+
#redo = [];
|
|
99
|
+
#references = /* @__PURE__ */ new WeakMap();
|
|
100
|
+
constructor(gramlot) {
|
|
101
|
+
this.gramlot = gramlot;
|
|
102
|
+
this.Source = gramlot.src.source.constructor;
|
|
103
|
+
this.Bag = gramlot.data.constructor;
|
|
104
|
+
}
|
|
105
|
+
get state() {
|
|
106
|
+
return { undo: this.#undo.at(-1)?.label ?? "", redo: this.#redo.at(-1)?.label ?? "" };
|
|
107
|
+
}
|
|
108
|
+
clear() {
|
|
109
|
+
this.#undo = [];
|
|
110
|
+
this.#redo = [];
|
|
111
|
+
}
|
|
112
|
+
#ref(node) {
|
|
113
|
+
if (!this.#references.has(node)) this.#references.set(node, { node });
|
|
114
|
+
return this.#references.get(node);
|
|
115
|
+
}
|
|
116
|
+
#bind(ref, node) {
|
|
117
|
+
ref.node = node;
|
|
118
|
+
this.#references.set(node, ref);
|
|
119
|
+
}
|
|
120
|
+
#capture(value) {
|
|
121
|
+
if (!(value instanceof this.Bag)) return value;
|
|
122
|
+
return value.getNodes().map((node) => [
|
|
123
|
+
this.#ref(node),
|
|
124
|
+
node.nodeTag,
|
|
125
|
+
node.resolver,
|
|
126
|
+
Object.entries(node.getAttr()).sort(([a], [b]) => a.localeCompare(b)),
|
|
127
|
+
this.#capture(node.getValue(true))
|
|
128
|
+
]);
|
|
129
|
+
}
|
|
130
|
+
#equal(a, b) {
|
|
131
|
+
return Object.is(a, b) || Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((v, i) => this.#equal(v, b[i]));
|
|
132
|
+
}
|
|
133
|
+
#commit(label, capture, redo, undo) {
|
|
134
|
+
const before = capture();
|
|
135
|
+
let error;
|
|
136
|
+
try {
|
|
137
|
+
redo();
|
|
138
|
+
} catch (caught) {
|
|
139
|
+
error = caught;
|
|
140
|
+
}
|
|
141
|
+
const after = capture();
|
|
142
|
+
if (!this.#equal(before, after)) {
|
|
143
|
+
this.#undo.push({ label, capture, before, after, undo, redo });
|
|
144
|
+
this.#redo = [];
|
|
145
|
+
}
|
|
146
|
+
if (error) throw error;
|
|
147
|
+
}
|
|
148
|
+
#step(from, to, direction, expected, result) {
|
|
149
|
+
const action = from.at(-1);
|
|
150
|
+
if (!action) return;
|
|
151
|
+
if (this.gramlot.state === "disposed") throw new Error("Inspected page disconnected");
|
|
152
|
+
if (!this.#equal(action.capture(), action[expected])) throw new Error("The target changed outside the inspector. Undo/Redo would overwrite those changes.");
|
|
153
|
+
let error;
|
|
154
|
+
try {
|
|
155
|
+
action[direction]();
|
|
156
|
+
} catch (caught) {
|
|
157
|
+
error = caught;
|
|
158
|
+
}
|
|
159
|
+
if (this.#equal(action.capture(), action[result])) {
|
|
160
|
+
from.pop();
|
|
161
|
+
to.push(action);
|
|
162
|
+
} else if (!error) error = new Error("The application changed the target during Undo/Redo.");
|
|
163
|
+
if (error) throw error;
|
|
164
|
+
}
|
|
165
|
+
undo() {
|
|
166
|
+
this.#step(this.#undo, this.#redo, "undo", "after", "before");
|
|
167
|
+
}
|
|
168
|
+
redo() {
|
|
169
|
+
this.#step(this.#redo, this.#undo, "redo", "before", "after");
|
|
170
|
+
}
|
|
171
|
+
edit(node, attrs, value, changeAttrs, changeValue) {
|
|
172
|
+
const ref = this.#ref(node), oldAttrs = { ...node.getAttr() }, oldValue = node.getValue(true);
|
|
173
|
+
const capture = () => [ref.node.parentBag, this.#captureNode(ref.node)];
|
|
174
|
+
const write = (attributes, content) => {
|
|
175
|
+
if (changeAttrs) ref.node.setAttr(attributes, true, false, false);
|
|
176
|
+
if (changeValue) ref.node.setValue(content);
|
|
177
|
+
};
|
|
178
|
+
this.#commit("Edit value or attributes", capture, () => write(attrs, value), () => write(oldAttrs, oldValue));
|
|
179
|
+
}
|
|
180
|
+
#captureNode(node) {
|
|
181
|
+
return [node.resolver, Object.entries(node.getAttr()).sort(([a], [b]) => a.localeCompare(b)), this.#capture(node.getValue(true))];
|
|
182
|
+
}
|
|
183
|
+
#sourceCapture = () => this.#capture(this.gramlot.src.source);
|
|
184
|
+
#node(path) {
|
|
185
|
+
if (typeof path !== "string" || !path) throw new Error("Select a Source node");
|
|
186
|
+
const node = this.gramlot.src.source.getNode(path);
|
|
187
|
+
if (!node || node.resolver) throw new Error("Source node is missing or deferred");
|
|
188
|
+
return node;
|
|
189
|
+
}
|
|
190
|
+
#removable(node) {
|
|
191
|
+
if (node.parentBag === this.gramlot.src.source) throw new Error("The page Source root cannot be removed or moved");
|
|
192
|
+
}
|
|
193
|
+
#saved(node) {
|
|
194
|
+
return { ref: this.#ref(node), label: node.label, tag: node.nodeTag, value: node.getValue(true), attrs: { ...node.getAttr() } };
|
|
195
|
+
}
|
|
196
|
+
#restore(saved, bag, index) {
|
|
197
|
+
if (bag.getNode(saved.label)) throw new Error(`Source label already exists: ${saved.label}`);
|
|
198
|
+
try {
|
|
199
|
+
bag.setItem(saved.label, saved.value, saved.attrs, index, false, false, "inspector", false, true, null, saved.tag);
|
|
200
|
+
} finally {
|
|
201
|
+
const inserted = bag.getNode(saved.label);
|
|
202
|
+
if (inserted) this.#bind(saved.ref, inserted);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
#parentState(parent) {
|
|
206
|
+
return { value: parent.getValue(true), attrs: { ...parent.getAttr() } };
|
|
207
|
+
}
|
|
208
|
+
#setParent(parent, state) {
|
|
209
|
+
parent.setValue(state.value, true, state.attrs, false);
|
|
210
|
+
parent.setAttr(state.attrs, true, false, false);
|
|
211
|
+
}
|
|
212
|
+
childFields(parent) {
|
|
213
|
+
const specifications = parent._getMeta("gramlot_component")?.childParameters ?? {};
|
|
214
|
+
return Object.entries(specifications).filter(([, spec]) => spec.required).map(([name, spec]) => {
|
|
215
|
+
const children = parent.getValue(true);
|
|
216
|
+
const used = spec.unique && children instanceof this.Source ? children.getNodes().map((child) => child.getAttr(name)) : [];
|
|
217
|
+
return { name, choices: spec.enum.filter((value) => !used.includes(value)) };
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
validateChild(parent, attrs, moving = null) {
|
|
221
|
+
const specifications = parent._getMeta("gramlot_component")?.childParameters ?? {};
|
|
222
|
+
for (const [name, spec] of Object.entries(specifications)) {
|
|
223
|
+
const value = attrs[name];
|
|
224
|
+
if (spec.required && value == null) throw new Error(`Choose ${name} before inserting the child`);
|
|
225
|
+
if (spec.enum && value != null && !spec.enum.includes(value)) throw new Error(`Invalid ${name}: ${value}`);
|
|
226
|
+
const children = parent.getValue(true);
|
|
227
|
+
if (spec.unique && children instanceof this.Source && children.getNodes().some((child) => child !== moving && child.getAttr(name) === value)) {
|
|
228
|
+
throw new Error(`${name} is already in use: ${value}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catalog(path) {
|
|
233
|
+
const node = this.#node(path), builder = node.builder;
|
|
234
|
+
return Object.entries(builder.schema).filter(([, info]) => !info._meta?.data_element && !info._meta?.subbuilder && !info._meta?.container).map(([tag, info]) => ({ tag, kind: info._meta?.gramlot_component ? "component" : "html", fields: this.childFields(node) }));
|
|
235
|
+
}
|
|
236
|
+
insert(path, requestedTag, attrs = {}) {
|
|
237
|
+
const parent = this.#node(path), builder = parent.builder;
|
|
238
|
+
const tag = builder.schemaTag(requestedTag);
|
|
239
|
+
if (!this.catalog(path).some((entry) => entry.tag === tag)) throw new Error("Choose an available component or HTML tag");
|
|
240
|
+
this.validateChild(parent, attrs);
|
|
241
|
+
const previous = this.#parentState(parent), parentRef = this.#ref(parent);
|
|
242
|
+
let saved, promoted;
|
|
243
|
+
const redo = () => {
|
|
244
|
+
if (saved) {
|
|
245
|
+
if (!(previous.value instanceof this.Source)) this.#setParent(parentRef.node, promoted);
|
|
246
|
+
this.#restore(saved, parentRef.node.getValue(true), parentRef.node.getValue(true).getNodes().length);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const existing = previous.value instanceof this.Source ? new Set(previous.value.getNodes()) : /* @__PURE__ */ new Set();
|
|
250
|
+
try {
|
|
251
|
+
builder.commandOnNode(parentRef.node, tag, null, attrs);
|
|
252
|
+
} finally {
|
|
253
|
+
const body = parentRef.node.getValue(true);
|
|
254
|
+
if (body instanceof this.Source) {
|
|
255
|
+
const added = body.getNodes().find((node) => !existing.has(node));
|
|
256
|
+
if (added) {
|
|
257
|
+
saved = this.#saved(added);
|
|
258
|
+
promoted = this.#parentState(parentRef.node);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
const undo = () => {
|
|
264
|
+
if (saved) saved.ref.node.parentBag.popNode(saved.ref.node.label, "inspector");
|
|
265
|
+
if (!(previous.value instanceof this.Source)) this.#setParent(parentRef.node, previous);
|
|
266
|
+
};
|
|
267
|
+
this.#commit("Add element", this.#sourceCapture, redo, undo);
|
|
268
|
+
return `${path}.${saved.label}`;
|
|
269
|
+
}
|
|
270
|
+
remove(path) {
|
|
271
|
+
const node = this.#node(path);
|
|
272
|
+
this.#removable(node);
|
|
273
|
+
const saved = this.#saved(node), bag = node.parentBag, index = bag.getNodes().indexOf(node);
|
|
274
|
+
this.#commit(
|
|
275
|
+
"Remove branch",
|
|
276
|
+
this.#sourceCapture,
|
|
277
|
+
() => saved.ref.node.parentBag.popNode(saved.label, "inspector"),
|
|
278
|
+
() => this.#restore(saved, bag, index)
|
|
279
|
+
);
|
|
280
|
+
return path.slice(0, path.lastIndexOf("."));
|
|
281
|
+
}
|
|
282
|
+
move(path, destination, placement) {
|
|
283
|
+
if (!["before", "inside", "after"].includes(placement)) throw new Error("Invalid drop position");
|
|
284
|
+
const node = this.#node(path), target = this.#node(destination);
|
|
285
|
+
this.#removable(node);
|
|
286
|
+
if (path === destination || destination.startsWith(path + ".")) throw new Error("A branch cannot be moved into itself");
|
|
287
|
+
const parent = placement === "inside" ? target : target.parentBag.parentNode;
|
|
288
|
+
if (!parent) throw new Error("Drop inside the page Source root");
|
|
289
|
+
const builder = parent.builder;
|
|
290
|
+
if (node.builder !== builder) throw new Error("Branches cannot cross builder dialects");
|
|
291
|
+
this.validateChild(parent, node.getAttr(), node);
|
|
292
|
+
const parentRef = this.#ref(parent);
|
|
293
|
+
const previous = this.#parentState(parent), origin = node.parentBag, oldIndex = origin.getNodes().indexOf(node);
|
|
294
|
+
const body = previous.value;
|
|
295
|
+
if (body instanceof this.Source && body !== origin && body.getNode(node.label)) throw new Error(`Source label already exists: ${node.label}`);
|
|
296
|
+
const children = body instanceof this.Source ? body.getNodes().filter((child) => child !== node) : [];
|
|
297
|
+
if (parent.nodeTag) {
|
|
298
|
+
builder.validateParent(node.nodeTag, parent.nodeTag);
|
|
299
|
+
builder.validateChildren(parent.nodeTag, [...children.map((child) => child.nodeTag), node.nodeTag]);
|
|
300
|
+
}
|
|
301
|
+
let index = placement === "inside" ? children.length : children.indexOf(target) + (placement === "after" ? 1 : 0);
|
|
302
|
+
if (index < 0) throw new Error("Drop target changed");
|
|
303
|
+
if (body === origin) {
|
|
304
|
+
const ref = this.#ref(node);
|
|
305
|
+
this.#commit("Move branch", this.#sourceCapture, () => origin.move(origin.getNodes().indexOf(ref.node), index), () => origin.move(origin.getNodes().indexOf(ref.node), oldIndex));
|
|
306
|
+
} else {
|
|
307
|
+
const saved = this.#saved(node);
|
|
308
|
+
const destinationBag = body instanceof this.Source ? body : new this.Source(null, builder);
|
|
309
|
+
let promoted;
|
|
310
|
+
this.#commit("Move branch", this.#sourceCapture, () => {
|
|
311
|
+
if (!(body instanceof this.Source)) {
|
|
312
|
+
if (promoted) this.#setParent(parentRef.node, promoted);
|
|
313
|
+
else {
|
|
314
|
+
builder.promoteNodeValue(parentRef.node, body, destinationBag);
|
|
315
|
+
promoted = this.#parentState(parentRef.node);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
saved.ref.node.parentBag.popNode(saved.label, "inspector");
|
|
319
|
+
this.#restore(saved, destinationBag, index);
|
|
320
|
+
}, () => {
|
|
321
|
+
saved.ref.node.parentBag.popNode(saved.label, "inspector");
|
|
322
|
+
this.#restore(saved, origin, oldIndex);
|
|
323
|
+
if (!(body instanceof this.Source)) this.#setParent(parentRef.node, previous);
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
return `${placement === "inside" ? destination : destination.slice(0, destination.lastIndexOf("."))}.${node.label}`;
|
|
327
|
+
}
|
|
328
|
+
};
|
|
96
329
|
var InspectorStyles = class {
|
|
97
330
|
#document;
|
|
98
331
|
#element = null;
|
|
@@ -168,6 +401,7 @@
|
|
|
168
401
|
const document2 = gramlot.src.renderer.destination.ownerDocument;
|
|
169
402
|
const window2 = document2.defaultView;
|
|
170
403
|
const styles = new InspectorStyles(document2);
|
|
404
|
+
const history = new InspectorHistory(gramlot);
|
|
171
405
|
const subscriber = `inspector-bridge-${window2.crypto.getRandomValues(new Uint32Array(4)).join("-")}`;
|
|
172
406
|
const identities = /* @__PURE__ */ new WeakMap();
|
|
173
407
|
const versions = /* @__PURE__ */ new WeakMap();
|
|
@@ -202,7 +436,8 @@
|
|
|
202
436
|
const snapshot = () => ({
|
|
203
437
|
data: describe(bag("data"), "data"),
|
|
204
438
|
source: describe(bag("source"), "source"),
|
|
205
|
-
breakpoints: [...breakpoints.values()].map(({ test, ...record }) => record)
|
|
439
|
+
breakpoints: [...breakpoints.values()].map(({ test, ...record }) => record),
|
|
440
|
+
history: history.state
|
|
206
441
|
});
|
|
207
442
|
const send = (data) => {
|
|
208
443
|
if (!stopped) port.postMessage(data);
|
|
@@ -275,8 +510,7 @@
|
|
|
275
510
|
if (node.resolver || !scalarType(node.getValue(true))) throw new Error("This value is read-only");
|
|
276
511
|
value = decodeScalar2(command.value);
|
|
277
512
|
}
|
|
278
|
-
|
|
279
|
-
if (Object.hasOwn(command, "value")) node.setValue(value);
|
|
513
|
+
history.edit(node, attrs, value, !!(command.set.length || command.remove.length), Object.hasOwn(command, "value"));
|
|
280
514
|
};
|
|
281
515
|
const setBreakpoint = (command) => {
|
|
282
516
|
bag(command.root);
|
|
@@ -302,10 +536,27 @@
|
|
|
302
536
|
send({ type: "result", id: message.id, ok: true, styles: styles.snapshot() });
|
|
303
537
|
return;
|
|
304
538
|
}
|
|
305
|
-
|
|
539
|
+
let selection;
|
|
540
|
+
if (message.type === "catalog") {
|
|
541
|
+
send({ type: "result", id: message.id, ok: true, catalog: history.catalog(message.command.path) });
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (["insert", "remove", "move"].includes(message.type)) {
|
|
545
|
+
const command = message.command, node = bag("source").getNode(command.path);
|
|
546
|
+
if (!node || identity(node) !== command.nodeId || (versions.get(node) ?? 0) !== command.revision) throw new Error("Source node changed. Select it again.");
|
|
547
|
+
if (message.type === "insert") selection = history.insert(command.path, command.tag, command.attrs);
|
|
548
|
+
if (message.type === "remove") selection = history.remove(command.path);
|
|
549
|
+
if (message.type === "move") {
|
|
550
|
+
const target = bag("source").getNode(command.destination);
|
|
551
|
+
if (!target || identity(target) !== command.targetId || (versions.get(target) ?? 0) !== command.targetRevision) throw new Error("Drop target changed. Try again.");
|
|
552
|
+
selection = history.move(command.path, command.destination, command.placement);
|
|
553
|
+
}
|
|
554
|
+
} else if (message.type === "undo") history.undo();
|
|
555
|
+
else if (message.type === "redo") history.redo();
|
|
556
|
+
else if (message.type === "edit") edit(message.command);
|
|
306
557
|
else if (message.type === "breakpoint") setBreakpoint(message.command);
|
|
307
558
|
else if (message.type !== "refresh") throw new Error(`Unknown inspector command: ${message.type}`);
|
|
308
|
-
send({ type: "result", id: message.id, ok: true, snapshot: snapshot() });
|
|
559
|
+
send({ type: "result", id: message.id, ok: true, selection, snapshot: snapshot() });
|
|
309
560
|
} catch (error) {
|
|
310
561
|
send({ type: "result", id: message.id, ok: false, error: error.message });
|
|
311
562
|
}
|
|
@@ -316,6 +567,7 @@
|
|
|
316
567
|
stopped = true;
|
|
317
568
|
for (const root of roots) bag(root).unsubscribe(subscriber, { any: true });
|
|
318
569
|
breakpoints.clear();
|
|
570
|
+
history.clear();
|
|
319
571
|
styles.dispose();
|
|
320
572
|
port.removeEventListener("message", receive);
|
|
321
573
|
window2.removeEventListener("pagehide", dispose);
|
|
@@ -347,6 +599,7 @@
|
|
|
347
599
|
error = "";
|
|
348
600
|
breakpoints = [];
|
|
349
601
|
styles = null;
|
|
602
|
+
history = { undo: "", redo: "" };
|
|
350
603
|
#info = /* @__PURE__ */ new WeakMap();
|
|
351
604
|
#listeners = /* @__PURE__ */ new Set();
|
|
352
605
|
#pending = /* @__PURE__ */ new Map();
|
|
@@ -378,6 +631,7 @@
|
|
|
378
631
|
if (message.snapshot) {
|
|
379
632
|
for (const root of roots2) this.#reconcile(this[root], message.snapshot[root]);
|
|
380
633
|
this.breakpoints = message.snapshot.breakpoints;
|
|
634
|
+
this.history = message.snapshot.history;
|
|
381
635
|
this.state = "started";
|
|
382
636
|
this.error = "";
|
|
383
637
|
} else if (message.type === "error") this.error = message.error;
|
|
@@ -388,7 +642,7 @@
|
|
|
388
642
|
const pending = this.#pending.get(message.id);
|
|
389
643
|
if (pending) {
|
|
390
644
|
this.#pending.delete(message.id);
|
|
391
|
-
if (message.ok && !this.error) pending.resolve();
|
|
645
|
+
if (message.ok && !this.error) pending.resolve(message);
|
|
392
646
|
else pending.reject(new Error(message.error || this.error));
|
|
393
647
|
}
|
|
394
648
|
}
|
|
@@ -451,8 +705,8 @@
|
|
|
451
705
|
this.#notify();
|
|
452
706
|
}
|
|
453
707
|
};
|
|
454
|
-
var gramlot_tools_inspector_default = ":host { all: initial; color-scheme: light; font: 12px/1.4 system-ui, sans-serif; color: #38414b; }\n* { box-sizing: border-box; }\nbutton, input, select { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\nbutton:focus-visible, input:focus-visible, select:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.tree { padding: 7px 3px; }\n.properties { background: white; }\n.properties-heading { font-size: 11px; display: flex; align-items: center; justify-content: space-between; height: 29px; padding: 0 8px; background: #f1f3f5; color: #6d7989; border-bottom: 1px solid #d1d7df; }\n.properties-heading button { background: white; border: 1px solid #c5cdda; border-radius: 2px; width: 23px; height: 23px; padding: 0; font-size: 18px; line-height: 20px; }\nfieldset { border: 0; margin: 0; padding: 0; min-width: 0; }\n.property-row { display: grid; grid-template-columns: minmax(95px, 30%) minmax(0, 1fr); min-height: 20px; border-bottom: 1px solid #d1d7df; font-size: 11px; }\n.property-name { display: flex; align-items: center; justify-content: flex-end; background: #888; color: white; font-weight: 700; padding: 1px 6px; border-right: 1px solid #d1d7df; overflow-wrap: anywhere; text-align: right; }\n.property-value { display: flex; align-items: center; min-width: 0; }\n.property-row input { border: 0; border-radius: 0; min-width: 0; width: 100%; height: 19px; padding: 1px 5px; background: transparent; }\n.property-name input { color: white; text-align: right; padding: 0; }\n.property-value input { flex: 1; }\n.property-value input[type=checkbox] { flex: none; width: 14px; height: 14px; margin: 2px 6px; }\n.property-value select { max-width: 82px; height: 20px; padding: 0; border: 0; border-left: 1px solid #d1d7df; background: #f1f3f5; font-size: 10px; }\n.remove { display: inline-flex; align-items: center; justify-content: center; margin-left: auto; flex: none; width: 22px; height: 20px; padding: 3px; border: 0; background: transparent; color: #7c8797; opacity: 0; }\n.remove svg { width: 13px; height: 13px; }\n.property-row:hover .remove, .property-row:focus-within .remove { opacity: 1; }\n.remove:hover { color: #b82323; background: #fbe9e9; }\n:disabled { cursor: default; opacity: .65; }\n.path { flex: none; padding: 5px 9px; border-top: 1px solid #c9cfd6; background: #f5f7f9; color: #697687; font-size: 11px; min-height: 27px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status, .breakpoint-line { font-size: 11px; margin: 0; padding: 3px 8px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status { color: #a12121; }\n.breakpoint-line { background: #fff2ed; color: #854127; border-bottom: 1px solid #d1d7df; }\n.error:empty, .edit-status:empty, .breakpoint-status:empty, .breakpoint-line:empty { display: none; }\n.breakpoint-dialog { width: min(340px, 90vw); color: #38414b; border: 1px solid #bbc3cf; border-radius: 4px; padding: 12px; box-shadow: 0 8px 28px #0003; font: 12px/1.4 system-ui, sans-serif; }\n.breakpoint-dialog::backdrop { background: #0002; }\n.breakpoint-dialog h2 { font-size: 13px; margin: 0 0 10px; overflow-wrap: anywhere; }\n.breakpoint-dialog select, .breakpoint-dialog input { width: 100%; border: 1px solid #bbc3cf; padding: 4px; margin: 0 0 7px; background: white; }\n.dialog-actions { display: flex; gap: 6px; justify-content: flex-end; margin-top: 7px; }\n.dialog-actions button { padding: 3px 10px; border: 1px solid #bbc3cf; border-radius: 3px; background: #f1f3f5; }\n.heading-label { flex: 1; }\n.properties-heading .breakpoint-count { width: auto; padding: 0 5px; margin-right: 5px; font-size: 11px; color: #b04a35; }\n.breakpoint-entry { display: flex; align-items: center; gap: 6px; padding: 4px 0; border-bottom: 1px solid #d1d7df; }\n.breakpoint-entry span { flex: 1; overflow-wrap: anywhere; }\n.breakpoint-entry button { background: transparent; border: 0; font-size: 17px; }\n[hidden] { display: none !important; }\n.targetbar { flex: none; height: 28px; padding: 2px 6px; background: #edf2fa; border-bottom: 1px solid #dadce0; }\n.targetbar select { width: 100%; height: 23px; border: 0; background: transparent; font-size: 11px; }\n.styles-panel { flex: 1; min-height: 0; overflow: auto; background: #fff; font-size: 11px; }\n.styles-toolbar { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 8px; background: #f1f3f5; border-bottom: 1px solid #d1d7df; }\n.styles-toolbar span { flex: 1; font-weight: 600; }\n.styles-toolbar button, .styles-toolbar a { padding: 3px 7px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.styles-toolbar a { color: inherit; text-decoration: none; }\n.styles-toolbar a[aria-disabled=true] { cursor: default; opacity: .65; }\n.styles-toolbar a:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.styles-help, .styles-empty, .styles-status { margin: 0; padding: 7px 9px; color: #697687; }\n.styles-status { color: #a12121; }\n.styles-status:empty { display: none; }\n.styles-group h3 { margin: 0; padding: 6px 9px; font-size: 11px; background: #edf2fa; border-block: 1px solid #d1d7df; }\n.style-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 25px 23px; align-items: center; gap: 8px; min-width: 0; padding: 3px 9px; border-bottom: 1px solid #e8ebef; }\n.style-row label { min-width: 0; font: 11px/1.4 ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.style-row input { min-width: 0; width: 100%; height: 23px; padding: 2px 5px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.style-row input[type=color] { width: 25px; padding: 1px; cursor: pointer; }\n.style-row button { grid-column: 4; width: 23px; height: 23px; padding: 0; border: 1px solid #c5cdda; border-radius: 3px; background: #f5f7f9; font-size: 15px; }\n\n:host([embedded]) { display: block; height: 100%; min-height: 0; }\n:host([embedded]) > div { height: 100%; }\n.embedded-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; overflow: hidden; }\n\n.property-value select.enum-value { flex: 1; min-width: 0; max-width: none; width: 100%; border: 0; background: white; font: inherit; padding: 1px 5px; }\n\n/* Presentation changes preserve the inspector runtime and selection. */\n:host([hidden]) { display: none; }\n:host([docked]) { display: block; height: 100%; min-height: 0; }\n:host([docked][hidden]) { display: none; }\n:host([docked]) > div { height: 100%; }\n:host([docked]) .targetbar select { min-height: 40px; font-size: 16px; }\n:host([docked]) .property-row { min-height: 36px; font-size: 13px; }\n:host([docked]) .property-row input { min-height: 35px; font-size: 16px; }\n:host([docked]) .remove { opacity: 1; min-height: 35px; width: 32px; }\n\n:host([docked]) { --tree-action-size: 28px; --tree-font-size: 14px; --tree-row-height: 40px; --separator-size: 14px; }\n:host([docked]) .targetbar { height: 44px; }\n:host([docked]) gramlot-poc-tabs > button { height: 44px; font-size: 14px; }\n:host([docked]) .properties-heading { height: 40px; font-size: 13px; }\n:host([docked]) .properties-heading button { width: 36px; height: 36px; }\n:host([docked]) .property-value select { height: 35px; font-size: 14px; }\n";
|
|
455
|
-
var gramlot_poc_tree_default = "/* Copyright 2025-2026 Softwell S.r.l. - SPDX-License-Identifier: Apache-2.0\n * Inspector subset of the DevTools storeTree stylesheet and inspector.css variables. */\n:host { display:block; font:var(--tree-font-size,11px)/var(--tree-row-height,18px) -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; color:#38414b; }\n:host([hidden]) { display:none; }\nul { list-style:none; margin:0; padding-left:17px; }\n.tree-root { padding-left:calc(var(--tree-action-size,14px) + 2px); }\n.tree-root > ul { padding-left:2px; }\nsummary, .leaf { position:relative; }\nli { line-height:var(--tree-row-height,18px); }\nsummary { display:flex; align-items:center; gap:7px; padding:0 5px; cursor:pointer; user-select:none; list-style:none; }\nsummary::-webkit-details-marker { display:none; }\nsummary::before { content:''; width:5px; height:5px; border-right:1.5px solid #78818a; border-bottom:1.5px solid #78818a; transform:rotate(-45deg); flex:none; margin:0 3px; }\ndetails[open] > summary::before { transform:rotate(45deg); }\n.leaf { display:flex; align-items:center; gap:7px; padding:0 5px 0 23px; cursor:pointer; }\nsummary:hover,.leaf:hover { background:#f0f3f6; }\n.selected,.selected:hover { background:transparent; color:#315dbd; font-weight:700; border-radius:2px; }\n.caption { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n/* Reserve a left gutter; showing an action must not shift the node label. */\n.actions { position:absolute; left:calc(-1 * var(--tree-action-size,14px)); top:0; display:inline-flex; opacity:0; pointer-events:none; }\nsummary:hover > .actions,.leaf:hover > .actions,summary:focus-visible > .actions,.leaf:focus-visible > .actions,\n.actions:has(button:focus-visible),.actions:has(button.active) { opacity:1; pointer-events:auto; }\n.actions button { border:0; background:transparent; color:#80868b; font:inherit; font-size:11px; line-height:var(--tree-row-height,18px); width:var(--tree-action-size,14px); height:var(--tree-row-height,18px); padding:0; cursor:pointer; border-radius:3px; }\n.actions button:hover { background:#e1e5ed; }\n.actions button[data-action=breakpoint] { font-size:0; }\n.actions button[data-action=breakpoint]::before { content:''; display:inline-block; box-sizing:border-box; width:8px; height:8px; border:1.5px solid currentColor; border-radius:50%; vertical-align:middle; }\n.actions button.active { color:#b3261e; }\n.actions button.active.conditional { color:#f9ab00; }\n.actions button.active[data-action=breakpoint]::before { background:currentColor; }\n.actions button:focus-visible,summary:focus-visible,.leaf:focus-visible { outline:2px solid #356f9f; outline-offset:-2px; }\n\n@media (hover: none) { .actions { opacity:1; pointer-events:auto; } }\n";
|
|
708
|
+
var gramlot_tools_inspector_default = ":host { all: initial; color-scheme: light; font: 12px/1.4 system-ui, sans-serif; color: #38414b; }\n* { box-sizing: border-box; }\nbutton, input, select { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\nbutton:focus-visible, input:focus-visible, select:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.tree { padding: 7px 3px; }\n.properties { background: white; }\n.properties-heading { font-size: 11px; display: flex; align-items: center; justify-content: space-between; height: 29px; padding: 0 8px; background: #f1f3f5; color: #6d7989; border-bottom: 1px solid #d1d7df; }\n.properties-heading button { background: white; border: 1px solid #c5cdda; border-radius: 2px; width: 23px; height: 23px; padding: 0; font-size: 18px; line-height: 20px; }\nfieldset { border: 0; margin: 0; padding: 0; min-width: 0; }\n.property-row { display: grid; grid-template-columns: minmax(95px, 30%) minmax(0, 1fr); min-height: 20px; border-bottom: 1px solid #d1d7df; font-size: 11px; }\n.property-name { display: flex; align-items: center; justify-content: flex-end; background: #888; color: white; font-weight: 700; padding: 1px 6px; border-right: 1px solid #d1d7df; overflow-wrap: anywhere; text-align: right; }\n.property-value { display: flex; align-items: center; min-width: 0; }\n.property-row input { border: 0; border-radius: 0; min-width: 0; width: 100%; height: 19px; padding: 1px 5px; background: transparent; }\n.property-name input { color: white; text-align: right; padding: 0; }\n.property-value input { flex: 1; }\n.property-value input[type=checkbox] { flex: none; width: 14px; height: 14px; margin: 2px 6px; }\n.property-value select { max-width: 82px; height: 20px; padding: 0; border: 0; border-left: 1px solid #d1d7df; background: #f1f3f5; font-size: 10px; }\n.remove { display: inline-flex; align-items: center; justify-content: center; margin-left: auto; flex: none; width: 22px; height: 20px; padding: 3px; border: 0; background: transparent; color: #7c8797; opacity: 0; }\n.remove svg { width: 13px; height: 13px; }\n.property-row:hover .remove, .property-row:focus-within .remove { opacity: 1; }\n.remove:hover { color: #b82323; background: #fbe9e9; }\n:disabled { cursor: default; opacity: .65; }\n.path { flex: none; padding: 5px 9px; border-top: 1px solid #c9cfd6; background: #f5f7f9; color: #697687; font-size: 11px; min-height: 27px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status, .breakpoint-line { font-size: 11px; margin: 0; padding: 3px 8px; overflow-wrap: anywhere; }\n.error, .edit-status, .breakpoint-status { color: #a12121; }\n.breakpoint-line { background: #fff2ed; color: #854127; border-bottom: 1px solid #d1d7df; }\n.error:empty, .edit-status:empty, .breakpoint-status:empty, .breakpoint-line:empty { display: none; }\n.breakpoint-dialog { width: min(340px, 90vw); color: #38414b; border: 1px solid #bbc3cf; border-radius: 4px; padding: 12px; box-shadow: 0 8px 28px #0003; font: 12px/1.4 system-ui, sans-serif; }\n.breakpoint-dialog::backdrop { background: #0002; }\n.breakpoint-dialog h2 { font-size: 13px; margin: 0 0 10px; overflow-wrap: anywhere; }\n.breakpoint-dialog select, .breakpoint-dialog input { width: 100%; border: 1px solid #bbc3cf; padding: 4px; margin: 0 0 7px; background: white; }\n.dialog-actions { display: flex; gap: 6px; justify-content: flex-end; margin-top: 7px; }\n.dialog-actions button { padding: 3px 10px; border: 1px solid #bbc3cf; border-radius: 3px; background: #f1f3f5; }\n.heading-label { flex: 1; }\n.properties-heading .breakpoint-count { width: auto; padding: 0 5px; margin-right: 5px; font-size: 11px; color: #b04a35; }\n.breakpoint-entry { display: flex; align-items: center; gap: 6px; padding: 4px 0; border-bottom: 1px solid #d1d7df; }\n.breakpoint-entry span { flex: 1; overflow-wrap: anywhere; }\n.breakpoint-entry button { background: transparent; border: 0; font-size: 17px; }\n[hidden] { display: none !important; }\n.targetbar { flex: none; height: 28px; padding: 2px 6px; background: #edf2fa; border-bottom: 1px solid #dadce0; }\n.targetbar select { width: 100%; height: 23px; border: 0; background: transparent; font-size: 11px; }\n.styles-panel { flex: 1; min-height: 0; overflow: auto; background: #fff; font-size: 11px; }\n.styles-toolbar { position: sticky; top: 0; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 8px; background: #f1f3f5; border-bottom: 1px solid #d1d7df; }\n.styles-toolbar span { flex: 1; font-weight: 600; }\n.styles-toolbar button, .styles-toolbar a { padding: 3px 7px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.styles-toolbar a { color: inherit; text-decoration: none; }\n.styles-toolbar a[aria-disabled=true] { cursor: default; opacity: .65; }\n.styles-toolbar a:focus-visible { outline: 1px solid #3574cb; outline-offset: -1px; }\n.styles-help, .styles-empty, .styles-status { margin: 0; padding: 7px 9px; color: #697687; }\n.styles-status { color: #a12121; }\n.styles-status:empty { display: none; }\n.styles-group h3 { margin: 0; padding: 6px 9px; font-size: 11px; background: #edf2fa; border-block: 1px solid #d1d7df; }\n.style-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 25px 23px; align-items: center; gap: 8px; min-width: 0; padding: 3px 9px; border-bottom: 1px solid #e8ebef; }\n.style-row label { min-width: 0; font: 11px/1.4 ui-monospace, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.style-row input { min-width: 0; width: 100%; height: 23px; padding: 2px 5px; border: 1px solid #c5cdda; border-radius: 3px; background: white; }\n.style-row input[type=color] { width: 25px; padding: 1px; cursor: pointer; }\n.style-row button { grid-column: 4; width: 23px; height: 23px; padding: 0; border: 1px solid #c5cdda; border-radius: 3px; background: #f5f7f9; font-size: 15px; }\n\n:host([embedded]) { display: block; height: 100%; min-height: 0; }\n:host([embedded]) > div { height: 100%; }\n.embedded-panel { display: flex; flex-direction: column; height: 100%; min-height: 0; overflow: hidden; }\n\n.property-value select.enum-value { flex: 1; min-width: 0; max-width: none; width: 100%; border: 0; background: white; font: inherit; padding: 1px 5px; }\n\n/* Presentation changes preserve the inspector runtime and selection. */\n:host([hidden]) { display: none; }\n:host([docked]) { display: block; height: 100%; min-height: 0; }\n:host([docked][hidden]) { display: none; }\n:host([docked]) > div { height: 100%; }\n:host([docked]) .targetbar select { min-height: 40px; font-size: 16px; }\n:host([docked]) .property-row { min-height: 36px; font-size: 13px; }\n:host([docked]) .property-row input { min-height: 35px; font-size: 16px; }\n:host([docked]) .remove { opacity: 1; min-height: 35px; width: 32px; }\n\n:host([docked]) { --tree-action-size: 28px; --tree-font-size: 14px; --tree-row-height: 40px; --separator-size: 14px; }\n:host([docked]) .targetbar { height: 44px; }\n:host([docked]) gramlot-poc-tabs > button { height: 44px; font-size: 14px; }\n:host([docked]) .properties-heading { height: 40px; font-size: 13px; }\n:host([docked]) .properties-heading button { width: 36px; height: 36px; }\n:host([docked]) .property-value select { height: 35px; font-size: 14px; }\n\n.history-toolbar { flex:none; display:flex; align-items:center; gap:6px; padding:4px 8px; border-bottom:1px solid #d1d7df; background:#f6f8fb; font:11px/1.4 system-ui,sans-serif; }\n.history-toolbar button { flex:none; padding:3px 6px; border:1px solid #c5cdda; border-radius:3px; background:white; cursor:pointer; }\n.history-toolbar button:disabled { opacity:.45; cursor:default; }\n.history-toolbar span { min-width:0; color:#a12121; overflow-wrap:anywhere; }\n";
|
|
709
|
+
var gramlot_poc_tree_default = "/* Copyright 2025-2026 Softwell S.r.l. - SPDX-License-Identifier: Apache-2.0\n * Inspector subset of the DevTools storeTree stylesheet and inspector.css variables. */\n:host { display:block; font:var(--tree-font-size,11px)/var(--tree-row-height,18px) -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; color:#38414b; }\n:host([hidden]) { display:none; }\nul { list-style:none; margin:0; padding-left:17px; }\n.tree-root { padding-left:calc(var(--tree-action-size,14px) + 2px); }\n.tree-root > ul { padding-left:2px; }\nsummary, .leaf { position:relative; }\nli { line-height:var(--tree-row-height,18px); }\nsummary { display:flex; align-items:center; gap:7px; padding:0 5px; cursor:pointer; user-select:none; list-style:none; }\nsummary::-webkit-details-marker { display:none; }\nsummary::before { content:''; width:5px; height:5px; border-right:1.5px solid #78818a; border-bottom:1.5px solid #78818a; transform:rotate(-45deg); flex:none; margin:0 3px; }\ndetails[open] > summary::before { transform:rotate(45deg); }\n.leaf { display:flex; align-items:center; gap:7px; padding:0 5px 0 23px; cursor:pointer; }\nsummary:hover,.leaf:hover { background:#f0f3f6; }\n.selected,.selected:hover { background:transparent; color:#315dbd; font-weight:700; border-radius:2px; }\n.caption { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n/* Reserve a left gutter; showing an action must not shift the node label. */\n.actions { position:absolute; left:calc(-1 * var(--tree-action-size,14px)); top:0; display:inline-flex; opacity:0; pointer-events:none; }\nsummary:hover > .actions,.leaf:hover > .actions,summary:focus-visible > .actions,.leaf:focus-visible > .actions,\n.actions:has(button:focus-visible),.actions:has(button.active) { opacity:1; pointer-events:auto; }\n.actions button { border:0; background:transparent; color:#80868b; font:inherit; font-size:11px; line-height:var(--tree-row-height,18px); width:var(--tree-action-size,14px); height:var(--tree-row-height,18px); padding:0; cursor:pointer; border-radius:3px; }\n.actions button:hover { background:#e1e5ed; }\n.actions button[data-action=breakpoint] { font-size:0; }\n.actions button[data-action=breakpoint]::before { content:''; display:inline-block; box-sizing:border-box; width:8px; height:8px; border:1.5px solid currentColor; border-radius:50%; vertical-align:middle; }\n.actions button.active { color:#b3261e; }\n.actions button.active.conditional { color:#f9ab00; }\n.actions button.active[data-action=breakpoint]::before { background:currentColor; }\n.actions button:focus-visible,summary:focus-visible,.leaf:focus-visible { outline:2px solid #356f9f; outline-offset:-2px; }\n\n@media (hover: none) { .actions { opacity:1; pointer-events:auto; } }\n\n.actions-end { position:static; margin-left:auto; flex:none; }\n[data-drop=inside] { outline:2px solid #356f9f; outline-offset:-2px; background:#e7f0fc; }\n[data-drop=before] { box-shadow:inset 0 2px #356f9f; }\n[data-drop=after] { box-shadow:inset 0 -2px #356f9f; }\n";
|
|
456
710
|
var sequence = 0;
|
|
457
711
|
var GramlotPocTree = class extends HTMLElement {
|
|
458
712
|
constructor() {
|
|
@@ -468,6 +722,9 @@
|
|
|
468
722
|
this._expanded = /* @__PURE__ */ new Set();
|
|
469
723
|
this._nodes = /* @__PURE__ */ new Map();
|
|
470
724
|
this._rowActions = [];
|
|
725
|
+
this.dragEnabled = false;
|
|
726
|
+
this.fixedPaths = [];
|
|
727
|
+
this._drag = null;
|
|
471
728
|
this._pendingRender = null;
|
|
472
729
|
this._subId = `gramlot-poc-tree-${++sequence}`;
|
|
473
730
|
}
|
|
@@ -495,6 +752,12 @@
|
|
|
495
752
|
this._selectedPath = path;
|
|
496
753
|
if (this.isConnected) this._markSelection();
|
|
497
754
|
}
|
|
755
|
+
revealPath(path) {
|
|
756
|
+
for (const details of this._root.querySelectorAll("details")) {
|
|
757
|
+
if (path.startsWith(details.dataset.path + ".")) details.open = true;
|
|
758
|
+
}
|
|
759
|
+
this.selectedPath = path;
|
|
760
|
+
}
|
|
498
761
|
get rowActions() {
|
|
499
762
|
return this._rowActions;
|
|
500
763
|
}
|
|
@@ -524,12 +787,22 @@
|
|
|
524
787
|
}
|
|
525
788
|
_render() {
|
|
526
789
|
this._pendingRender = null;
|
|
790
|
+
const focused = this.shadowRoot.activeElement;
|
|
791
|
+
const focusedPath = focused?.closest("[data-node-path]")?.dataset.nodePath;
|
|
792
|
+
const focusedAction = focused?.dataset.action;
|
|
527
793
|
for (const details of this._root.querySelectorAll("details")) {
|
|
528
794
|
if (details.open) this._expanded.add(details.dataset.path);
|
|
529
795
|
else this._expanded.delete(details.dataset.path);
|
|
530
796
|
}
|
|
531
797
|
this._nodes.clear();
|
|
532
798
|
this._root.replaceChildren(...this._store ? [this._buildLevel(this._store, "", /* @__PURE__ */ new Set())] : []);
|
|
799
|
+
if (focusedPath) {
|
|
800
|
+
let path = focusedPath;
|
|
801
|
+
while (path && !this._nodes.has(path)) path = path.includes(".") ? path.slice(0, path.lastIndexOf(".")) : "";
|
|
802
|
+
const row = [...this._root.querySelectorAll("[data-node-path]")].find((item) => item.dataset.nodePath === path);
|
|
803
|
+
const action = focusedAction && row && [...row.querySelectorAll("button")].find((button) => button.dataset.action === focusedAction);
|
|
804
|
+
(action || row)?.focus({ preventScroll: true });
|
|
805
|
+
}
|
|
533
806
|
if (this._selectedPath !== null && !this._nodes.has(this._selectedPath)) {
|
|
534
807
|
this._selectedPath = null;
|
|
535
808
|
this._notifySelection();
|
|
@@ -572,35 +845,91 @@
|
|
|
572
845
|
row.append(caption);
|
|
573
846
|
row.addEventListener("click", () => this._select(path));
|
|
574
847
|
this._actions(row, path, node);
|
|
848
|
+
this._dragEvents(row, path, node);
|
|
575
849
|
list.append(item);
|
|
576
850
|
}
|
|
577
851
|
return list;
|
|
578
852
|
}
|
|
579
853
|
_actions(row, path, node) {
|
|
580
854
|
if (!this._rowActions.length) return;
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
855
|
+
for (const position of ["start", "end"]) {
|
|
856
|
+
const actions = this.ownerDocument.createElement("span");
|
|
857
|
+
actions.className = `actions actions-${position}`;
|
|
858
|
+
for (const action of this._rowActions) {
|
|
859
|
+
if ((action.position ?? "start") !== position || action.hiddenPaths?.includes(path)) continue;
|
|
860
|
+
const button = this.ownerDocument.createElement("button");
|
|
861
|
+
button.type = "button";
|
|
862
|
+
button.textContent = action.icon ?? action.label;
|
|
863
|
+
button.title = action.label;
|
|
864
|
+
button.setAttribute("aria-label", action.label);
|
|
865
|
+
button.dataset.action = action.id;
|
|
866
|
+
button.classList.toggle("active", action.activePaths?.includes(path) ?? false);
|
|
867
|
+
button.classList.toggle("conditional", action.conditionalPaths?.includes(path) ?? false);
|
|
868
|
+
button.addEventListener("click", (event) => {
|
|
869
|
+
event.preventDefault();
|
|
870
|
+
event.stopPropagation();
|
|
871
|
+
this.dispatchEvent(new this.ownerDocument.defaultView.CustomEvent("tree-action", {
|
|
872
|
+
bubbles: true,
|
|
873
|
+
composed: true,
|
|
874
|
+
detail: { action: action.id, path, node }
|
|
875
|
+
}));
|
|
876
|
+
});
|
|
877
|
+
actions.append(button);
|
|
878
|
+
}
|
|
879
|
+
if (actions.childElementCount) row.append(actions);
|
|
602
880
|
}
|
|
603
|
-
|
|
881
|
+
}
|
|
882
|
+
_clearDrop() {
|
|
883
|
+
for (const row of this._root.querySelectorAll("[data-drop]")) delete row.dataset.drop;
|
|
884
|
+
}
|
|
885
|
+
_dragEvents(row, path, node) {
|
|
886
|
+
if (!this.dragEnabled) return;
|
|
887
|
+
row.draggable = !this.fixedPaths.includes(path);
|
|
888
|
+
row.addEventListener("dragstart", (event) => {
|
|
889
|
+
if (!row.draggable || event.target.closest("button")) {
|
|
890
|
+
event.preventDefault();
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
event.stopPropagation();
|
|
894
|
+
this._drag = { path, node };
|
|
895
|
+
event.dataTransfer.effectAllowed = "move";
|
|
896
|
+
event.dataTransfer.setData("application/x-gramlot-source", this._subId);
|
|
897
|
+
});
|
|
898
|
+
const placement = (event) => {
|
|
899
|
+
const rect = row.getBoundingClientRect();
|
|
900
|
+
const fraction = (event.clientY - rect.top) / rect.height;
|
|
901
|
+
return this.fixedPaths.includes(path) ? "inside" : fraction < 0.25 ? "before" : fraction > 0.75 ? "after" : "inside";
|
|
902
|
+
};
|
|
903
|
+
const valid = () => this._drag && this._drag.path !== path && !path.startsWith(this._drag.path + ".");
|
|
904
|
+
row.addEventListener("dragover", (event) => {
|
|
905
|
+
if (!valid()) return;
|
|
906
|
+
event.preventDefault();
|
|
907
|
+
event.stopPropagation();
|
|
908
|
+
event.dataTransfer.dropEffect = "move";
|
|
909
|
+
this._clearDrop();
|
|
910
|
+
row.dataset.drop = placement(event);
|
|
911
|
+
});
|
|
912
|
+
row.addEventListener("dragleave", () => {
|
|
913
|
+
delete row.dataset.drop;
|
|
914
|
+
});
|
|
915
|
+
row.addEventListener("drop", (event) => {
|
|
916
|
+
event.preventDefault();
|
|
917
|
+
event.stopPropagation();
|
|
918
|
+
this._clearDrop();
|
|
919
|
+
if (!valid() || event.dataTransfer.getData("application/x-gramlot-source") !== this._subId) return;
|
|
920
|
+
const source = this._drag;
|
|
921
|
+
this._drag = null;
|
|
922
|
+
if (this._store.getNode(source.path) !== source.node) return;
|
|
923
|
+
this.dispatchEvent(new this.ownerDocument.defaultView.CustomEvent("tree-drop", {
|
|
924
|
+
bubbles: true,
|
|
925
|
+
composed: true,
|
|
926
|
+
detail: { path: source.path, destination: path, placement: placement(event) }
|
|
927
|
+
}));
|
|
928
|
+
});
|
|
929
|
+
row.addEventListener("dragend", () => {
|
|
930
|
+
this._drag = null;
|
|
931
|
+
this._clearDrop();
|
|
932
|
+
});
|
|
604
933
|
}
|
|
605
934
|
_markSelection() {
|
|
606
935
|
for (const row of this._root.querySelectorAll("[data-node-path]")) {
|
|
@@ -777,6 +1106,9 @@
|
|
|
777
1106
|
}
|
|
778
1107
|
}
|
|
779
1108
|
#target = null;
|
|
1109
|
+
#history = null;
|
|
1110
|
+
#insertTarget = null;
|
|
1111
|
+
#catalog = [];
|
|
780
1112
|
#connection = null;
|
|
781
1113
|
#connectionRelease = null;
|
|
782
1114
|
#targets = [];
|
|
@@ -1020,6 +1352,67 @@
|
|
|
1020
1352
|
inspector.#applyEdit(choose);
|
|
1021
1353
|
} else choose();
|
|
1022
1354
|
}
|
|
1355
|
+
sourceAction(node, event) {
|
|
1356
|
+
if (event.detail.action === "breakpoint") {
|
|
1357
|
+
this.openBreakpoint(node, event);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
const run = () => {
|
|
1361
|
+
if (event.detail.action === "insert") inspector.#openInsert(event.detail.path);
|
|
1362
|
+
if (event.detail.action === "remove") {
|
|
1363
|
+
try {
|
|
1364
|
+
inspector.#runCommand("remove", inspector.#sourceCommand(event.detail.path));
|
|
1365
|
+
} catch (error) {
|
|
1366
|
+
ui.data.setItem("status", error.message);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1370
|
+
if (ui.data.getItem("editor.dirty")) inspector.#applyEdit(run);
|
|
1371
|
+
else run();
|
|
1372
|
+
}
|
|
1373
|
+
sourceDrop(node, event) {
|
|
1374
|
+
const run = () => {
|
|
1375
|
+
try {
|
|
1376
|
+
const { path, destination, placement } = event.detail;
|
|
1377
|
+
const command = inspector.#sourceCommand(path);
|
|
1378
|
+
const target = inspector.#sourceCommand(destination);
|
|
1379
|
+
inspector.#runCommand("move", { ...command, destination, placement, targetId: target.nodeId, targetRevision: target.revision });
|
|
1380
|
+
} catch (error) {
|
|
1381
|
+
ui.data.setItem("status", error.message);
|
|
1382
|
+
}
|
|
1383
|
+
};
|
|
1384
|
+
if (ui.data.getItem("editor.dirty")) inspector.#applyEdit(run);
|
|
1385
|
+
else run();
|
|
1386
|
+
}
|
|
1387
|
+
insertKind() {
|
|
1388
|
+
inspector.#insertChoices();
|
|
1389
|
+
}
|
|
1390
|
+
addElement() {
|
|
1391
|
+
inspector.#runCommand("insert", { ...inspector.#insertTarget, tag: ui.data.getItem("insert.tag"), attrs: Object.fromEntries((inspector.#catalog[0]?.fields ?? []).map(({ name }) => [name, ui.data.getItem(`insert.attrs.${name}`)])) });
|
|
1392
|
+
}
|
|
1393
|
+
closeInsert() {
|
|
1394
|
+
inspector.#dialog("insert").close();
|
|
1395
|
+
inspector.#insertTarget = null;
|
|
1396
|
+
}
|
|
1397
|
+
undo() {
|
|
1398
|
+
if (ui.data.getItem("editor.dirty")) inspector.#applyEdit(() => inspector.#runCommand("undo"));
|
|
1399
|
+
else inspector.#runCommand("undo");
|
|
1400
|
+
}
|
|
1401
|
+
redo() {
|
|
1402
|
+
if (ui.data.getItem("editor.dirty")) inspector.#applyEdit(() => inspector.#runCommand("redo"));
|
|
1403
|
+
else inspector.#runCommand("redo");
|
|
1404
|
+
}
|
|
1405
|
+
historyKey(node, event) {
|
|
1406
|
+
if (!(event.metaKey || event.ctrlKey) || event.altKey || event.target.closest("input,textarea,select,[contenteditable]")) return;
|
|
1407
|
+
if (event.key.toLowerCase() === "z") {
|
|
1408
|
+
event.preventDefault();
|
|
1409
|
+
event.shiftKey ? this.redo() : this.undo();
|
|
1410
|
+
}
|
|
1411
|
+
if (event.key.toLowerCase() === "y") {
|
|
1412
|
+
event.preventDefault();
|
|
1413
|
+
this.redo();
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1023
1416
|
openBreakpoint(node, event) {
|
|
1024
1417
|
if (event.detail.action !== "breakpoint") return;
|
|
1025
1418
|
ui.data.setItem("breakpointDirty", false);
|
|
@@ -1089,6 +1482,8 @@
|
|
|
1089
1482
|
breakpointCount: "\u25CF 0",
|
|
1090
1483
|
noBreakpoints: true
|
|
1091
1484
|
})) ui.data.setItem(key, value);
|
|
1485
|
+
ui.data.setItem("history", new Bag({ noUndo: true, noRedo: true, undo: "", redo: "" }));
|
|
1486
|
+
ui.data.setItem("insert", new Bag({ kind: "html", tag: "", html: true, component: false, status: "" }));
|
|
1092
1487
|
ui.data.setItem("editor", new Bag({ dirty: false, disabled: true, status: "", mode: "", condition: "" }));
|
|
1093
1488
|
ui.data.setItem("breakpoints", new Bag());
|
|
1094
1489
|
ui.data.setItem("breakpointDirty", false);
|
|
@@ -1096,7 +1491,7 @@
|
|
|
1096
1491
|
const builder = new GramlotBuilder();
|
|
1097
1492
|
const root = builder.root;
|
|
1098
1493
|
root.style(gramlot_tools_inspector_default);
|
|
1099
|
-
const palette = this.hasAttribute("embedded") ? root.section({ node_label: "palette", class: "embedded-panel", "aria-label": "Gramlot inspector" }) : root.webcomponent({ code: "gramlot-poc-palette", node_label: "palette", title: "Gramlot inspector", docked: this.hasAttribute("docked") ? "" : null, connect_onclose: "inspector.close" });
|
|
1494
|
+
const palette = this.hasAttribute("embedded") ? root.section({ node_label: "palette", class: "embedded-panel", "aria-label": "Gramlot inspector", connect_onkeydown: "inspector.historyKey" }) : root.webcomponent({ code: "gramlot-poc-palette", node_label: "palette", title: "Gramlot inspector", docked: this.hasAttribute("docked") ? "" : null, connect_onclose: "inspector.close", connect_onkeydown: "inspector.historyKey" });
|
|
1100
1495
|
const targetbar = palette.div({ node_label: "targetbar", class: "targetbar", hidden: "^singleTarget" });
|
|
1101
1496
|
targetbar.select({ node_label: "targets", value: "^targetId", disabled: "^busy", "aria-label": "Inspected page", connect_onchange: "inspector.selectTarget" });
|
|
1102
1497
|
const toolbar = palette.webcomponent({ code: "gramlot-poc-tabs", node_label: "tabs", role: "tablist", "aria-label": "Inspected root" });
|
|
@@ -1108,6 +1503,10 @@
|
|
|
1108
1503
|
"aria-selected": "false",
|
|
1109
1504
|
connect_onclick: "inspector.selectRoot"
|
|
1110
1505
|
});
|
|
1506
|
+
const historybar = palette.div({ class: "history-toolbar", hidden: "^stylesActive" });
|
|
1507
|
+
historybar.html_button("\u21B6 Undo", { type: "button", disabled: "^history.noUndo", title: "^history.undo", connect_onclick: "inspector.undo" });
|
|
1508
|
+
historybar.html_button("\u21B7 Redo", { type: "button", disabled: "^history.noRedo", title: "^history.redo", connect_onclick: "inspector.redo" });
|
|
1509
|
+
historybar.span("^status", { role: "status" });
|
|
1111
1510
|
palette.p("^error", { role: "alert", class: "error" });
|
|
1112
1511
|
const content = palette.webcomponent({ code: "gramlot-poc-splitter", node_label: "content", hidden: "^stylesActive" });
|
|
1113
1512
|
const trees = content.div({ node_label: "tree", slot: "top", class: "tree" });
|
|
@@ -1117,7 +1516,8 @@
|
|
|
1117
1516
|
"data-root": name,
|
|
1118
1517
|
hidden: name === "data" ? "^sourceActive" : "^dataActive",
|
|
1119
1518
|
connect_onchange: "inspector.selectNode",
|
|
1120
|
-
"connect_ontree-action": "inspector.
|
|
1519
|
+
"connect_ontree-action": "inspector.sourceAction",
|
|
1520
|
+
"connect_ontree-drop": "inspector.sourceDrop"
|
|
1121
1521
|
});
|
|
1122
1522
|
const properties = content.section({ node_label: "properties", slot: "bottom", class: "properties", "aria-label": "Selected node properties" });
|
|
1123
1523
|
const heading = properties.div({ class: "properties-heading" });
|
|
@@ -1169,6 +1569,19 @@
|
|
|
1169
1569
|
list.h2("Active breakpoints");
|
|
1170
1570
|
list.div({ node_label: "entries" });
|
|
1171
1571
|
list.div({ class: "dialog-actions" }).html_button("Close", { type: "button", connect_onclick: "inspector.closeBreakpoints" });
|
|
1572
|
+
const insert = palette.dialog({ node_label: "insert", "aria-label": "Add Source element", class: "breakpoint-dialog", connect_oncancel: "inspector.closeInsert" });
|
|
1573
|
+
insert.h2("Add a child element");
|
|
1574
|
+
const kind = insert.select({ value: "^insert.kind", "aria-label": "Element kind", connect_onchange: "inspector.insertKind" });
|
|
1575
|
+
kind.option("HTML tag", { value: "html" });
|
|
1576
|
+
kind.option("Widget or container", { value: "component" });
|
|
1577
|
+
insert.select({ node_label: "components", value: "^insert.tag", hidden: "^insert.html", "aria-label": "Widget or container" });
|
|
1578
|
+
insert.input({ value: "^insert.tag", live: true, hidden: "^insert.component", list: `${this.#subscriber}-tags`, "aria-label": "HTML tag", placeholder: "div, span\u2026" });
|
|
1579
|
+
insert.datalist({ node_label: "tags", id: `${this.#subscriber}-tags` });
|
|
1580
|
+
insert.div({ node_label: "fields" });
|
|
1581
|
+
insert.p("^insert.status", { role: "status" });
|
|
1582
|
+
const insertActions = insert.div({ class: "dialog-actions" });
|
|
1583
|
+
insertActions.html_button("Cancel", { type: "button", connect_onclick: "inspector.closeInsert" });
|
|
1584
|
+
insertActions.html_button("Add", { type: "button", disabled: "^busy", connect_onclick: "inspector.addElement" });
|
|
1172
1585
|
ui.src.startSource(builder.source);
|
|
1173
1586
|
for (const name of ["data", "source"]) this.#trees[name] = ui.dom.getDomNode(ui.src.source.getNode(`main.palette.content.tree.${name}`));
|
|
1174
1587
|
this.#renderTargets();
|
|
@@ -1194,6 +1607,7 @@
|
|
|
1194
1607
|
return;
|
|
1195
1608
|
}
|
|
1196
1609
|
if (!this.#target) return;
|
|
1610
|
+
this.#history = new InspectorHistory(this.#target);
|
|
1197
1611
|
this.#subscriptions = [this.#target.data, this.#target.src.source];
|
|
1198
1612
|
for (const [index, bag] of this.#subscriptions.entries()) bag.subscribe(this.#subscriber, { any: (event) => {
|
|
1199
1613
|
this.#checkBreakpoints(index === 0 ? "data" : "source", event);
|
|
@@ -1201,6 +1615,10 @@
|
|
|
1201
1615
|
} });
|
|
1202
1616
|
}
|
|
1203
1617
|
#unsubscribe() {
|
|
1618
|
+
this.#history?.clear();
|
|
1619
|
+
this.#history = null;
|
|
1620
|
+
this.#insertTarget = null;
|
|
1621
|
+
if (this.#ui) this.#dialog("insert").close();
|
|
1204
1622
|
++this.#styleRequest;
|
|
1205
1623
|
this.#styles?.dispose();
|
|
1206
1624
|
this.#styles = null;
|
|
@@ -1247,6 +1665,11 @@
|
|
|
1247
1665
|
ui.data.setItem("breakpoints", configurations);
|
|
1248
1666
|
ui.data.setItem("breakpointError", this.#connection.breakpoints.filter((record) => record.error).map((record) => `${record.root}: ${record.path}: ${record.error}`).join("; "));
|
|
1249
1667
|
}
|
|
1668
|
+
const history = this.#connection ? this.#connection.history : this.#history?.state;
|
|
1669
|
+
for (const action of ["undo", "redo"]) {
|
|
1670
|
+
ui.data.setItem(`history.${action}`, history?.[action] ?? "");
|
|
1671
|
+
ui.data.setItem(`history.no${action === "undo" ? "Undo" : "Redo"}`, !history?.[action] || ui.data.getItem("busy") || this.#state() !== "started");
|
|
1672
|
+
}
|
|
1250
1673
|
const count = ui.data.getItem("breakpoints").getNodes().length;
|
|
1251
1674
|
ui.data.setItem("breakpointCount", `\u25CF ${count}`);
|
|
1252
1675
|
ui.data.setItem("noBreakpoints", count === 0);
|
|
@@ -1256,13 +1679,18 @@
|
|
|
1256
1679
|
const tree = this.#trees[name];
|
|
1257
1680
|
tree.storeBag = this.#connection || this.#target ? this.#targetBag(name) : null;
|
|
1258
1681
|
const breakpoints = ui.data.getItem("breakpoints").getNodes().filter((node) => node.value.getItem("root") === name);
|
|
1682
|
+
tree.dragEnabled = name === "source";
|
|
1683
|
+
tree.fixedPaths = tree.storeBag?.getNodes().map((node) => node.label) ?? [];
|
|
1259
1684
|
tree.rowActions = [{
|
|
1260
1685
|
id: "breakpoint",
|
|
1261
1686
|
icon: "\u25CB",
|
|
1262
1687
|
label: "Breakpoint",
|
|
1263
1688
|
activePaths: breakpoints.map((node) => node.value.getItem("path")),
|
|
1264
1689
|
conditionalPaths: breakpoints.filter((node) => node.value.getItem("condition").trim()).map((node) => node.value.getItem("path"))
|
|
1265
|
-
}
|
|
1690
|
+
}, ...name === "source" ? [
|
|
1691
|
+
{ id: "insert", icon: "+", label: "Add child element", position: "end" },
|
|
1692
|
+
{ id: "remove", icon: "\u2212", label: "Remove branch", position: "end", hiddenPaths: tree.fixedPaths }
|
|
1693
|
+
] : []];
|
|
1266
1694
|
}
|
|
1267
1695
|
if (this.#target || this.#connection) this.#index(this.#bag(), []);
|
|
1268
1696
|
this.#trees[root].selectedPath = this.#selected()?.path.join(".") ?? null;
|
|
@@ -1632,8 +2060,7 @@ ${declarations}
|
|
|
1632
2060
|
});
|
|
1633
2061
|
return false;
|
|
1634
2062
|
}
|
|
1635
|
-
|
|
1636
|
-
if (!Object.is(value, this.#snapshot.value)) target.setValue(value);
|
|
2063
|
+
this.#history.edit(target, attrs, value, changed, !Object.is(value, this.#snapshot.value));
|
|
1637
2064
|
this.#acceptEdit(target);
|
|
1638
2065
|
this.#refresh();
|
|
1639
2066
|
this.#ui.data.setItem("editor.status", "");
|
|
@@ -1644,6 +2071,91 @@ ${declarations}
|
|
|
1644
2071
|
return false;
|
|
1645
2072
|
}
|
|
1646
2073
|
}
|
|
2074
|
+
#sourceCommand(path) {
|
|
2075
|
+
const node = this.#targetBag("source").getNode(path);
|
|
2076
|
+
if (!node) throw new Error("Source node no longer exists");
|
|
2077
|
+
const info = this.#connection?.nodeInfo(node);
|
|
2078
|
+
return { path, nodeId: info?.id, revision: info?.revision, ...this.#connection ? {} : { node } };
|
|
2079
|
+
}
|
|
2080
|
+
async #openInsert(path) {
|
|
2081
|
+
if (this.#ui.data.getItem("busy")) return;
|
|
2082
|
+
const generation = this.#generation;
|
|
2083
|
+
try {
|
|
2084
|
+
this.#insertTarget = this.#sourceCommand(path);
|
|
2085
|
+
this.#catalog = this.#connection ? (await this.#connection.request("catalog", { path })).catalog : this.#history.catalog(path);
|
|
2086
|
+
if (!this.#ui || generation !== this.#generation) return;
|
|
2087
|
+
this.#ui.data.setItem("insert.kind", "html");
|
|
2088
|
+
this.#ui.data.setItem("insert.status", "");
|
|
2089
|
+
this.#insertChoices();
|
|
2090
|
+
const builder = new GramlotBuilder();
|
|
2091
|
+
this.#ui.data.setItem("insert.attrs", new Bag());
|
|
2092
|
+
for (const { name, choices } of this.#catalog[0]?.fields ?? []) {
|
|
2093
|
+
builder.root.html_label(name);
|
|
2094
|
+
const field = builder.root.select({ value: `^insert.attrs.${name}`, "aria-label": name });
|
|
2095
|
+
field.option(`Choose ${name}\u2026`, { value: "", disabled: true });
|
|
2096
|
+
for (const value of choices) field.option(value, { value });
|
|
2097
|
+
this.#ui.data.setItem(`insert.attrs.${name}`, "");
|
|
2098
|
+
}
|
|
2099
|
+
this.#ui.src.source.getNode("main.palette.insert.fields").setValue(this.#ui.src.prepareSource(builder.source));
|
|
2100
|
+
this.#dialog("insert").showModal();
|
|
2101
|
+
} catch (error) {
|
|
2102
|
+
if (this.#ui && generation === this.#generation) this.#ui.data.setItem("status", error.message);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
#insertChoices() {
|
|
2106
|
+
const html = this.#ui.data.getItem("insert.kind") === "html";
|
|
2107
|
+
this.#ui.data.setItem("insert.html", html);
|
|
2108
|
+
this.#ui.data.setItem("insert.component", !html);
|
|
2109
|
+
const choices = this.#catalog.filter((item) => item.kind === (html ? "html" : "component"));
|
|
2110
|
+
const builder = new GramlotBuilder();
|
|
2111
|
+
for (const item of choices) builder.root.option(item.tag, { value: item.tag });
|
|
2112
|
+
this.#ui.src.source.getNode(`main.palette.insert.${html ? "tags" : "components"}`).setValue(this.#ui.src.prepareSource(builder.source));
|
|
2113
|
+
this.#ui.data.setItem("insert.tag", html ? "" : choices[0]?.tag ?? "");
|
|
2114
|
+
}
|
|
2115
|
+
async #runCommand(type, command = {}) {
|
|
2116
|
+
const ui = this.#ui;
|
|
2117
|
+
if (ui.data.getItem("busy")) return;
|
|
2118
|
+
const generation = this.#generation;
|
|
2119
|
+
ui.data.setItem("busy", true);
|
|
2120
|
+
ui.data.setItem("status", "");
|
|
2121
|
+
ui.data.setItem("insert.status", "");
|
|
2122
|
+
try {
|
|
2123
|
+
let selection;
|
|
2124
|
+
if (this.#connection) ({ selection } = await this.#connection.request(type, command));
|
|
2125
|
+
else {
|
|
2126
|
+
if (command.path && this.#targetBag("source").getNode(command.path) !== command.node) throw new Error("Source node changed. Select it again.");
|
|
2127
|
+
if (type === "insert") selection = this.#history.insert(command.path, command.tag, command.attrs);
|
|
2128
|
+
if (type === "remove") selection = this.#history.remove(command.path);
|
|
2129
|
+
if (type === "move") selection = this.#history.move(command.path, command.destination, command.placement);
|
|
2130
|
+
if (type === "undo") this.#history.undo();
|
|
2131
|
+
if (type === "redo") this.#history.redo();
|
|
2132
|
+
}
|
|
2133
|
+
if (!this.#ui || generation !== this.#generation) return;
|
|
2134
|
+
if (type === "insert") this.#dialog("insert").close();
|
|
2135
|
+
this.#snapshot = null;
|
|
2136
|
+
ui.data.setItem("editor.dirty", false);
|
|
2137
|
+
this.#refresh();
|
|
2138
|
+
if (selection) {
|
|
2139
|
+
ui.data.setItem("root", "source");
|
|
2140
|
+
ui.data.setItem("tab", "source");
|
|
2141
|
+
this.#refresh();
|
|
2142
|
+
const entry = this.#nodes.find((item) => item.path.join(".") === selection);
|
|
2143
|
+
ui.data.setItem("selection", entry?.id ?? null);
|
|
2144
|
+
this.#trees.source.revealPath(selection);
|
|
2145
|
+
this.#refresh();
|
|
2146
|
+
}
|
|
2147
|
+
} catch (error) {
|
|
2148
|
+
if (this.#ui && generation === this.#generation) {
|
|
2149
|
+
ui.data.setItem("status", error.message);
|
|
2150
|
+
ui.data.setItem("insert.status", error.message);
|
|
2151
|
+
}
|
|
2152
|
+
} finally {
|
|
2153
|
+
if (this.#ui && generation === this.#generation) {
|
|
2154
|
+
ui.data.setItem("busy", false);
|
|
2155
|
+
this.#refresh();
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
1647
2159
|
#findBreakpoint(root, path) {
|
|
1648
2160
|
return this.#ui.data.getItem("breakpoints").getNodes().find((node) => {
|
|
1649
2161
|
const value = node.getValue(true);
|
|
@@ -1801,7 +2313,7 @@ ${declarations}
|
|
|
1801
2313
|
}
|
|
1802
2314
|
|
|
1803
2315
|
// src/gramlot_examples/gallery/dist/theme-styles.js
|
|
1804
|
-
var appearanceStyles2 = { "base": "", "compact": '/* Gramlot Compact: load after gramlot-base/theme.css. Colors and behavior stay in Base. */\n@layer gramlot.tokens {\n :root {\n --gramlot-field-height: 28px;\n --gramlot-field-line-height: 1.35;\n --gramlot-field-padding: .25rem .5rem;\n --gramlot-field-font-size: 1rem;\n --gramlot-space-1: .2rem;\n --gramlot-space-2: .4rem;\n --gramlot-space-3: .5rem;\n --gramlot-space-4: .6rem;\n --gramlot-space-6: .9rem;\n --gramlot-space-8: 1.2rem;\n --gramlot-space-12: 1.8rem;\n --gramlot-radius-sm: .25rem;\n --gramlot-radius: .35rem;\n --gramlot-radius-lg: .4rem;\n }\n}\n\n@layer gramlot.base {\n html { font-size: 13px; }\n body { line-height: 1.35; }\n :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, figure) { margin-block: 0 .5rem; }\n h1 { font-size: 1.35rem; }\n h2 { font-size: 1.15rem; }\n h3 { font-size: 1.05rem; }\n pre { padding: .5rem; }\n blockquote { padding-inline-start: .6rem; }\n hr { margin-block: 1rem; }\n}\n\n@layer gramlot.components {\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) {\n min-block-size: 28px;\n padding: .25rem .5rem;\n font-size: 1rem;\n line-height: 1.35;\n }\n :where(label) { font-size: .95rem; }\n :where(input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="hidden"]), select, textarea) {\n min-block-size: var(--gramlot-field-height);\n padding: var(--gramlot-field-padding);\n font-size: var(--gramlot-field-font-size);\n line-height: var(--gramlot-field-line-height);\n }\n :where(textarea) { min-block-size: 5rem; }\n :where(input[type="color"]) { min-block-size: 28px; }\n :where(input[type="file"])::file-selector-button { margin-inline-end: .5rem; padding: .25rem .5rem; }\n :where(fieldset) { margin-block-end: .6rem; padding: .5rem; }\n :where(table) { font-size: 1rem; }\n :where(th, td) { padding: .4rem .5rem; }\n :where(details) { padding: .4rem .5rem; }\n :where(details[open] > summary) { margin-block-end: .5rem; }\n :where(dialog) { padding: .75rem; }\n}\n\n@layer gramlot.utilities {\n .example-page { inline-size: min(100% - 1.2rem, var(--gramlot-page-width)); padding-block: .6rem; }\n .card { padding: .6rem; box-shadow: none; }\n}\n', "mimi": '/* Gramlot Compact: load after gramlot-base/theme.css. Colors and behavior stay in Base. */\n@layer gramlot.tokens {\n :root {\n --gramlot-field-height: 28px;\n --gramlot-field-line-height: 1.35;\n --gramlot-field-padding: .25rem .5rem;\n --gramlot-field-font-size: 1rem;\n --gramlot-space-1: .2rem;\n --gramlot-space-2: .4rem;\n --gramlot-space-3: .5rem;\n --gramlot-space-4: .6rem;\n --gramlot-space-6: .9rem;\n --gramlot-space-8: 1.2rem;\n --gramlot-space-12: 1.8rem;\n --gramlot-radius-sm: .25rem;\n --gramlot-radius: .35rem;\n --gramlot-radius-lg: .4rem;\n }\n}\n\n@layer gramlot.base {\n html { font-size: 13px; }\n body { line-height: 1.35; }\n :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, figure) { margin-block: 0 .5rem; }\n h1 { font-size: 1.35rem; }\n h2 { font-size: 1.15rem; }\n h3 { font-size: 1.05rem; }\n pre { padding: .5rem; }\n blockquote { padding-inline-start: .6rem; }\n hr { margin-block: 1rem; }\n}\n\n@layer gramlot.components {\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) {\n min-block-size: 28px;\n padding: .25rem .5rem;\n font-size: 1rem;\n line-height: 1.35;\n }\n :where(label) { font-size: .95rem; }\n :where(input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="hidden"]), select, textarea) {\n min-block-size: var(--gramlot-field-height);\n padding: var(--gramlot-field-padding);\n font-size: var(--gramlot-field-font-size);\n line-height: var(--gramlot-field-line-height);\n }\n :where(textarea) { min-block-size: 5rem; }\n :where(input[type="color"]) { min-block-size: 28px; }\n :where(input[type="file"])::file-selector-button { margin-inline-end: .5rem; padding: .25rem .5rem; }\n :where(fieldset) { margin-block-end: .6rem; padding: .5rem; }\n :where(table) { font-size: 1rem; }\n :where(th, td) { padding: .4rem .5rem; }\n :where(details) { padding: .4rem .5rem; }\n :where(details[open] > summary) { margin-block-end: .5rem; }\n :where(dialog) { padding: .75rem; }\n}\n\n@layer gramlot.utilities {\n .example-page { inline-size: min(100% - 1.2rem, var(--gramlot-page-width)); padding-block: .6rem; }\n .card { padding: .6rem; box-shadow: none; }\n}\n\n/* Gramlot adaptation of legacy mimi; load after Base and Compact. */\n@layer gramlot.tokens {\n :root {\n --gramlot-background: #EDEEF0;\n --gramlot-surface: #F5F5F6;\n --gramlot-surface-subtle: #E0E1E3;\n --gramlot-ink: #3C3D40;\n --gramlot-text-secondary: #6B6E72;\n --gramlot-border: #BDBFC2;\n --gramlot-border-control: #9EA0A3;\n --gramlot-navigation: #48494C;\n --gramlot-navigation-text: #FFFFFF;\n --gramlot-action: #0071E3;\n --gramlot-action-hover: #005BBB;\n --gramlot-brand-blue: #0071E3;\n --gramlot-brand-yellow: #9EA0A3;\n --gramlot-selected: #E8F1FC;\n --gramlot-focus-ring: #0071E3;\n --gramlot-field-background: #FFFFFF;\n --gramlot-field-readonly-background: #E0E1E3;\n --gramlot-error: #B3261E;\n --gramlot-error-background: #FFF1F0;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 6%);\n --gramlot-radius-sm: 4px;\n --gramlot-radius: 3px;\n --gramlot-radius-lg: 3px;\n --gramlot-field-height: 18px;\n --gramlot-field-padding: 1px 3px;\n --gramlot-field-line-height: 1.15;\n --gramlot-field-font-size: 1rem;\n --gramlot-label-size: .9em;\n --gramlot-label-gap: 2px;\n --gramlot-label-color: var(--gramlot-text-secondary);\n --gramlot-space-4: 6px;\n --gramlot-font-ui: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;\n }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n --gramlot-background: #242527;\n --gramlot-surface: #303134;\n --gramlot-surface-subtle: #3C3D40;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #6B6E72;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3C3D40;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n }\n :root[data-theme="dark"] {\n --gramlot-background: #242527;\n --gramlot-surface: #303134;\n --gramlot-surface-subtle: #3C3D40;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #6B6E72;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3C3D40;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n}\n@layer gramlot.base {\n html { font-size: 12px; }\n}\n@layer gramlot.components {\n :where(label) { font-size: var(--gramlot-label-size); font-weight: normal; color: var(--gramlot-label-color); margin-block-end: var(--gramlot-label-gap); }\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) { min-block-size: 24px; padding: 2px 8px; font-weight: 500; }\n}\n@layer gramlot.utilities {\n .card { box-shadow: var(--gramlot-shadow); }\n}\n', "joanna": '/* Gramlot Compact: load after gramlot-base/theme.css. Colors and behavior stay in Base. */\n@layer gramlot.tokens {\n :root {\n --gramlot-field-height: 28px;\n --gramlot-field-line-height: 1.35;\n --gramlot-field-padding: .25rem .5rem;\n --gramlot-field-font-size: 1rem;\n --gramlot-space-1: .2rem;\n --gramlot-space-2: .4rem;\n --gramlot-space-3: .5rem;\n --gramlot-space-4: .6rem;\n --gramlot-space-6: .9rem;\n --gramlot-space-8: 1.2rem;\n --gramlot-space-12: 1.8rem;\n --gramlot-radius-sm: .25rem;\n --gramlot-radius: .35rem;\n --gramlot-radius-lg: .4rem;\n }\n}\n\n@layer gramlot.base {\n html { font-size: 13px; }\n body { line-height: 1.35; }\n :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, figure) { margin-block: 0 .5rem; }\n h1 { font-size: 1.35rem; }\n h2 { font-size: 1.15rem; }\n h3 { font-size: 1.05rem; }\n pre { padding: .5rem; }\n blockquote { padding-inline-start: .6rem; }\n hr { margin-block: 1rem; }\n}\n\n@layer gramlot.components {\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) {\n min-block-size: 28px;\n padding: .25rem .5rem;\n font-size: 1rem;\n line-height: 1.35;\n }\n :where(label) { font-size: .95rem; }\n :where(input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="hidden"]), select, textarea) {\n min-block-size: var(--gramlot-field-height);\n padding: var(--gramlot-field-padding);\n font-size: var(--gramlot-field-font-size);\n line-height: var(--gramlot-field-line-height);\n }\n :where(textarea) { min-block-size: 5rem; }\n :where(input[type="color"]) { min-block-size: 28px; }\n :where(input[type="file"])::file-selector-button { margin-inline-end: .5rem; padding: .25rem .5rem; }\n :where(fieldset) { margin-block-end: .6rem; padding: .5rem; }\n :where(table) { font-size: 1rem; }\n :where(th, td) { padding: .4rem .5rem; }\n :where(details) { padding: .4rem .5rem; }\n :where(details[open] > summary) { margin-block-end: .5rem; }\n :where(dialog) { padding: .75rem; }\n}\n\n@layer gramlot.utilities {\n .example-page { inline-size: min(100% - 1.2rem, var(--gramlot-page-width)); padding-block: .6rem; }\n .card { padding: .6rem; box-shadow: none; }\n}\n\n/* Gramlot adaptation of legacy joanna; load after Base and Compact. */\n@layer gramlot.tokens {\n :root {\n --gramlot-background: #F2F2F7;\n --gramlot-surface: #FFFFFF;\n --gramlot-surface-subtle: #F2F2F7;\n --gramlot-ink: #3A3A3C;\n --gramlot-text-secondary: #636366;\n --gramlot-border: #D1D1D6;\n --gramlot-border-control: #AEAEB2;\n --gramlot-navigation: #3A3A3C;\n --gramlot-navigation-text: #FFFFFF;\n --gramlot-action: #007AFF;\n --gramlot-action-hover: #0061CC;\n --gramlot-brand-blue: #007AFF;\n --gramlot-brand-yellow: #AEAEB2;\n --gramlot-selected: #E0EFFF;\n --gramlot-focus-ring: #007AFF;\n --gramlot-field-background: #FFFFFF;\n --gramlot-field-readonly-background: #F2F2F7;\n --gramlot-error: #B3261E;\n --gramlot-error-background: #FFF1F0;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 6%);\n --gramlot-radius-sm: 6px;\n --gramlot-radius: 6px;\n --gramlot-radius-lg: 6px;\n --gramlot-field-height: 20px;\n --gramlot-field-padding: 1px 3px;\n --gramlot-field-line-height: 1.15;\n --gramlot-field-font-size: 1rem;\n --gramlot-label-size: .8em;\n --gramlot-label-gap: 2px;\n --gramlot-label-color: var(--gramlot-text-secondary);\n --gramlot-space-4: 6px;\n --gramlot-font-ui: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;\n }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n --gramlot-background: #1C1C1E;\n --gramlot-surface: #2C2C2E;\n --gramlot-surface-subtle: #3A3A3C;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #636366;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3A3A3C;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n }\n :root[data-theme="dark"] {\n --gramlot-background: #1C1C1E;\n --gramlot-surface: #2C2C2E;\n --gramlot-surface-subtle: #3A3A3C;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #636366;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3A3A3C;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n}\n@layer gramlot.base {\n html { font-size: 13px; }\n}\n@layer gramlot.components {\n :where(label) { font-size: var(--gramlot-label-size); font-weight: normal; color: var(--gramlot-label-color); margin-block-end: var(--gramlot-label-gap); }\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) { min-block-size: 26px; padding: 2px 8px; font-weight: 500; }\n}\n@layer gramlot.utilities {\n .card { box-shadow: var(--gramlot-shadow); }\n}\n' };
|
|
2316
|
+
var appearanceStyles2 = { "base": "", "compact": '/* Gramlot Compact: load after gramlot-base/theme.css. Colors and behavior stay in Base. */\n@layer gramlot.tokens {\n :root {\n --gramlot-field-height: 28px;\n --gramlot-field-line-height: 1.35;\n --gramlot-field-padding: .25rem .5rem;\n --gramlot-field-font-size: 1rem;\n --gramlot-space-1: .2rem;\n --gramlot-space-2: .4rem;\n --gramlot-space-3: .5rem;\n --gramlot-space-4: .6rem;\n --gramlot-space-6: .9rem;\n --gramlot-space-8: 1.2rem;\n --gramlot-space-12: 1.8rem;\n --gramlot-radius-sm: .25rem;\n --gramlot-radius: .35rem;\n --gramlot-radius-lg: .4rem;\n }\n}\n\n@layer gramlot.base {\n html { font-size: 13px; }\n body { line-height: 1.35; }\n :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, figure) { margin-block: 0 .5rem; }\n h1 { font-size: 1.35rem; }\n h2 { font-size: 1.15rem; }\n h3 { font-size: 1.05rem; }\n pre { padding: .5rem; }\n blockquote { padding-inline-start: .6rem; }\n hr { margin-block: 1rem; }\n}\n\n@layer gramlot.components {\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) {\n min-block-size: 28px;\n padding: .25rem .5rem;\n font-size: 1rem;\n line-height: 1.35;\n }\n :where(label) { font-size: .95rem; }\n :where(input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="hidden"]), select, textarea) {\n min-block-size: var(--gramlot-field-height);\n padding: var(--gramlot-field-padding);\n font-size: var(--gramlot-field-font-size);\n line-height: var(--gramlot-field-line-height);\n }\n :where(textarea) { min-block-size: 5rem; }\n :where(input[type="color"]) { min-block-size: 28px; }\n :where(input[type="file"])::file-selector-button { margin-inline-end: .5rem; padding: .25rem .5rem; }\n :where(fieldset) { margin-block-end: .6rem; padding: .5rem; }\n :where(table) { font-size: 1rem; }\n :where(th, td) { padding: .4rem .5rem; }\n :where(details) { padding: .4rem .5rem; }\n :where(details[open] > summary) { margin-block-end: .5rem; }\n :where(dialog) { padding: .75rem; }\n}\n\n@layer gramlot.utilities {\n .example-page { inline-size: min(100% - 1.2rem, var(--gramlot-page-width)); padding-block: .6rem; }\n .card { padding: .6rem; box-shadow: none; }\n}\n', "mimi": '/* Gramlot Compact: load after gramlot-base/theme.css. Colors and behavior stay in Base. */\n@layer gramlot.tokens {\n :root {\n --gramlot-field-height: 28px;\n --gramlot-field-line-height: 1.35;\n --gramlot-field-padding: .25rem .5rem;\n --gramlot-field-font-size: 1rem;\n --gramlot-space-1: .2rem;\n --gramlot-space-2: .4rem;\n --gramlot-space-3: .5rem;\n --gramlot-space-4: .6rem;\n --gramlot-space-6: .9rem;\n --gramlot-space-8: 1.2rem;\n --gramlot-space-12: 1.8rem;\n --gramlot-radius-sm: .25rem;\n --gramlot-radius: .35rem;\n --gramlot-radius-lg: .4rem;\n }\n}\n\n@layer gramlot.base {\n html { font-size: 13px; }\n body { line-height: 1.35; }\n :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, figure) { margin-block: 0 .5rem; }\n h1 { font-size: 1.35rem; }\n h2 { font-size: 1.15rem; }\n h3 { font-size: 1.05rem; }\n pre { padding: .5rem; }\n blockquote { padding-inline-start: .6rem; }\n hr { margin-block: 1rem; }\n}\n\n@layer gramlot.components {\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) {\n min-block-size: 28px;\n padding: .25rem .5rem;\n font-size: 1rem;\n line-height: 1.35;\n }\n :where(label) { font-size: .95rem; }\n :where(input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="hidden"]), select, textarea) {\n min-block-size: var(--gramlot-field-height);\n padding: var(--gramlot-field-padding);\n font-size: var(--gramlot-field-font-size);\n line-height: var(--gramlot-field-line-height);\n }\n :where(textarea) { min-block-size: 5rem; }\n :where(input[type="color"]) { min-block-size: 28px; }\n :where(input[type="file"])::file-selector-button { margin-inline-end: .5rem; padding: .25rem .5rem; }\n :where(fieldset) { margin-block-end: .6rem; padding: .5rem; }\n :where(table) { font-size: 1rem; }\n :where(th, td) { padding: .4rem .5rem; }\n :where(details) { padding: .4rem .5rem; }\n :where(details[open] > summary) { margin-block-end: .5rem; }\n :where(dialog) { padding: .75rem; }\n}\n\n@layer gramlot.utilities {\n .example-page { inline-size: min(100% - 1.2rem, var(--gramlot-page-width)); padding-block: .6rem; }\n .card { padding: .6rem; box-shadow: none; }\n}\n\n/* Gramlot adaptation of legacy mimi; load after Base and Compact. */\n@layer gramlot.tokens {\n :root {\n --gramlot-tab-height: 24px;\n --gramlot-tab-padding: 3px 10px;\n --gramlot-tab-radius: 3px;\n --gramlot-tab-gap: 2px;\n --gramlot-tab-strip-padding: 3px;\n --gramlot-tab-background: var(--gramlot-background);\n --gramlot-tab-selected-background: var(--gramlot-surface);\n --gramlot-tab-selected-color: var(--gramlot-ink);\n --gramlot-tab-border: var(--gramlot-border);\n --gramlot-background: #EDEEF0;\n --gramlot-surface: #F5F5F6;\n --gramlot-surface-subtle: #E0E1E3;\n --gramlot-ink: #3C3D40;\n --gramlot-text-secondary: #6B6E72;\n --gramlot-border: #BDBFC2;\n --gramlot-border-control: #9EA0A3;\n --gramlot-navigation: #48494C;\n --gramlot-navigation-text: #FFFFFF;\n --gramlot-action: #0071E3;\n --gramlot-action-hover: #005BBB;\n --gramlot-brand-blue: #0071E3;\n --gramlot-brand-yellow: #9EA0A3;\n --gramlot-selected: #E8F1FC;\n --gramlot-focus-ring: #0071E3;\n --gramlot-field-background: #FFFFFF;\n --gramlot-field-readonly-background: #E0E1E3;\n --gramlot-error: #B3261E;\n --gramlot-error-background: #FFF1F0;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 6%);\n --gramlot-radius-sm: 4px;\n --gramlot-radius: 3px;\n --gramlot-radius-lg: 3px;\n --gramlot-field-height: 18px;\n --gramlot-field-padding: 1px 3px;\n --gramlot-field-line-height: 1.15;\n --gramlot-field-font-size: 1rem;\n --gramlot-label-size: .9em;\n --gramlot-label-gap: 2px;\n --gramlot-label-color: var(--gramlot-text-secondary);\n --gramlot-space-4: 6px;\n --gramlot-font-ui: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;\n }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n --gramlot-background: #242527;\n --gramlot-surface: #303134;\n --gramlot-surface-subtle: #3C3D40;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #6B6E72;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3C3D40;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n }\n :root[data-theme="dark"] {\n --gramlot-background: #242527;\n --gramlot-surface: #303134;\n --gramlot-surface-subtle: #3C3D40;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #6B6E72;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3C3D40;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n}\n@layer gramlot.base {\n html { font-size: 12px; }\n}\n@layer gramlot.components {\n :where(label) { font-size: var(--gramlot-label-size); font-weight: normal; color: var(--gramlot-label-color); margin-block-end: var(--gramlot-label-gap); }\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) { min-block-size: 24px; padding: 2px 8px; font-weight: 500; }\n}\n@layer gramlot.utilities {\n .card { box-shadow: var(--gramlot-shadow); }\n}\n', "joanna": '/* Gramlot Compact: load after gramlot-base/theme.css. Colors and behavior stay in Base. */\n@layer gramlot.tokens {\n :root {\n --gramlot-field-height: 28px;\n --gramlot-field-line-height: 1.35;\n --gramlot-field-padding: .25rem .5rem;\n --gramlot-field-font-size: 1rem;\n --gramlot-space-1: .2rem;\n --gramlot-space-2: .4rem;\n --gramlot-space-3: .5rem;\n --gramlot-space-4: .6rem;\n --gramlot-space-6: .9rem;\n --gramlot-space-8: 1.2rem;\n --gramlot-space-12: 1.8rem;\n --gramlot-radius-sm: .25rem;\n --gramlot-radius: .35rem;\n --gramlot-radius-lg: .4rem;\n }\n}\n\n@layer gramlot.base {\n html { font-size: 13px; }\n body { line-height: 1.35; }\n :where(h1, h2, h3, h4, h5, h6, p, ul, ol, dl, blockquote, pre, figure) { margin-block: 0 .5rem; }\n h1 { font-size: 1.35rem; }\n h2 { font-size: 1.15rem; }\n h3 { font-size: 1.05rem; }\n pre { padding: .5rem; }\n blockquote { padding-inline-start: .6rem; }\n hr { margin-block: 1rem; }\n}\n\n@layer gramlot.components {\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) {\n min-block-size: 28px;\n padding: .25rem .5rem;\n font-size: 1rem;\n line-height: 1.35;\n }\n :where(label) { font-size: .95rem; }\n :where(input:not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]):not([type="hidden"]), select, textarea) {\n min-block-size: var(--gramlot-field-height);\n padding: var(--gramlot-field-padding);\n font-size: var(--gramlot-field-font-size);\n line-height: var(--gramlot-field-line-height);\n }\n :where(textarea) { min-block-size: 5rem; }\n :where(input[type="color"]) { min-block-size: 28px; }\n :where(input[type="file"])::file-selector-button { margin-inline-end: .5rem; padding: .25rem .5rem; }\n :where(fieldset) { margin-block-end: .6rem; padding: .5rem; }\n :where(table) { font-size: 1rem; }\n :where(th, td) { padding: .4rem .5rem; }\n :where(details) { padding: .4rem .5rem; }\n :where(details[open] > summary) { margin-block-end: .5rem; }\n :where(dialog) { padding: .75rem; }\n}\n\n@layer gramlot.utilities {\n .example-page { inline-size: min(100% - 1.2rem, var(--gramlot-page-width)); padding-block: .6rem; }\n .card { padding: .6rem; box-shadow: none; }\n}\n\n/* Gramlot adaptation of legacy joanna; load after Base and Compact. */\n@layer gramlot.tokens {\n :root {\n --gramlot-tab-height: 26px;\n --gramlot-tab-padding: 3px 10px;\n --gramlot-tab-radius: 6px;\n --gramlot-tab-gap: 2px;\n --gramlot-tab-strip-padding: 3px;\n --gramlot-tab-background: var(--gramlot-background);\n --gramlot-tab-selected-background: var(--gramlot-surface);\n --gramlot-tab-selected-color: var(--gramlot-ink);\n --gramlot-tab-border: var(--gramlot-border);\n --gramlot-background: #F2F2F7;\n --gramlot-surface: #FFFFFF;\n --gramlot-surface-subtle: #F2F2F7;\n --gramlot-ink: #3A3A3C;\n --gramlot-text-secondary: #636366;\n --gramlot-border: #D1D1D6;\n --gramlot-border-control: #AEAEB2;\n --gramlot-navigation: #3A3A3C;\n --gramlot-navigation-text: #FFFFFF;\n --gramlot-action: #007AFF;\n --gramlot-action-hover: #0061CC;\n --gramlot-brand-blue: #007AFF;\n --gramlot-brand-yellow: #AEAEB2;\n --gramlot-selected: #E0EFFF;\n --gramlot-focus-ring: #007AFF;\n --gramlot-field-background: #FFFFFF;\n --gramlot-field-readonly-background: #F2F2F7;\n --gramlot-error: #B3261E;\n --gramlot-error-background: #FFF1F0;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 6%);\n --gramlot-radius-sm: 6px;\n --gramlot-radius: 6px;\n --gramlot-radius-lg: 6px;\n --gramlot-field-height: 20px;\n --gramlot-field-padding: 1px 3px;\n --gramlot-field-line-height: 1.15;\n --gramlot-field-font-size: 1rem;\n --gramlot-label-size: .8em;\n --gramlot-label-gap: 2px;\n --gramlot-label-color: var(--gramlot-text-secondary);\n --gramlot-space-4: 6px;\n --gramlot-font-ui: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;\n }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n --gramlot-background: #1C1C1E;\n --gramlot-surface: #2C2C2E;\n --gramlot-surface-subtle: #3A3A3C;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #636366;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3A3A3C;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n }\n :root[data-theme="dark"] {\n --gramlot-background: #1C1C1E;\n --gramlot-surface: #2C2C2E;\n --gramlot-surface-subtle: #3A3A3C;\n --gramlot-ink: #F2F2F7;\n --gramlot-text-secondary: #C7C7CC;\n --gramlot-border: #636366;\n --gramlot-border-control: #8E8E93;\n --gramlot-navigation: #1C1C1E;\n --gramlot-action: #78B7FF;\n --gramlot-action-hover: #A6CFFF;\n --gramlot-brand-blue: #3478CA;\n --gramlot-selected: #254163;\n --gramlot-focus-ring: #78B7FF;\n --gramlot-field-background: #202124;\n --gramlot-field-readonly-background: #3A3A3C;\n --gramlot-error: #FFB4AB;\n --gramlot-error-background: #482524;\n --gramlot-shadow: 0 1px 4px rgb(0 0 0 / 20%);\n }\n}\n@layer gramlot.base {\n html { font-size: 13px; }\n}\n@layer gramlot.components {\n :where(label) { font-size: var(--gramlot-label-size); font-weight: normal; color: var(--gramlot-label-color); margin-block-end: var(--gramlot-label-gap); }\n :where(button, input[type="button"], input[type="submit"], input[type="reset"], .button) { min-block-size: 26px; padding: 2px 8px; font-weight: 500; }\n}\n@layer gramlot.utilities {\n .card { box-shadow: var(--gramlot-shadow); }\n}\n' };
|
|
1805
2317
|
|
|
1806
2318
|
// src/gramlot_examples/gallery/browser/frame-theme.js
|
|
1807
2319
|
function mountFrameTheme(renderer, node) {
|