@upstart.gg/vite-plugins 0.1.29 → 0.1.30

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.
Files changed (50) hide show
  1. package/dist/upstart-editor-api.d.ts +13 -1
  2. package/dist/upstart-editor-api.d.ts.map +1 -1
  3. package/dist/upstart-editor-api.js +59 -1
  4. package/dist/upstart-editor-api.js.map +1 -1
  5. package/dist/vite-plugin-upstart-attrs.d.ts +12 -7
  6. package/dist/vite-plugin-upstart-attrs.d.ts.map +1 -1
  7. package/dist/vite-plugin-upstart-attrs.js +195 -3
  8. package/dist/vite-plugin-upstart-attrs.js.map +1 -1
  9. package/dist/vite-plugin-upstart-branding/plugin.d.ts +3 -3
  10. package/dist/vite-plugin-upstart-branding/plugin.d.ts.map +1 -1
  11. package/dist/vite-plugin-upstart-branding/plugin.js.map +1 -1
  12. package/dist/vite-plugin-upstart-branding/runtime.js.map +1 -1
  13. package/dist/vite-plugin-upstart-editor/plugin.d.ts +3 -3
  14. package/dist/vite-plugin-upstart-editor/plugin.d.ts.map +1 -1
  15. package/dist/vite-plugin-upstart-editor/plugin.js +4 -1
  16. package/dist/vite-plugin-upstart-editor/plugin.js.map +1 -1
  17. package/dist/vite-plugin-upstart-editor/runtime/click-handler.js +27 -16
  18. package/dist/vite-plugin-upstart-editor/runtime/click-handler.js.map +1 -1
  19. package/dist/vite-plugin-upstart-editor/runtime/error-handler.js.map +1 -1
  20. package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.js +1 -1
  21. package/dist/vite-plugin-upstart-editor/runtime/hover-overlay.js.map +1 -1
  22. package/dist/vite-plugin-upstart-editor/runtime/index.d.ts +1 -1
  23. package/dist/vite-plugin-upstart-editor/runtime/index.js +14 -2
  24. package/dist/vite-plugin-upstart-editor/runtime/index.js.map +1 -1
  25. package/dist/{src/vite-plugin-upstart-editor → vite-plugin-upstart-editor}/runtime/state.d.ts +1 -1
  26. package/dist/vite-plugin-upstart-editor/runtime/state.d.ts.map +1 -0
  27. package/dist/vite-plugin-upstart-editor/runtime/state.js.map +1 -0
  28. package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts.map +1 -1
  29. package/dist/vite-plugin-upstart-editor/runtime/text-editor.js +212 -28
  30. package/dist/vite-plugin-upstart-editor/runtime/text-editor.js.map +1 -1
  31. package/dist/vite-plugin-upstart-editor/runtime/types.d.ts +16 -3
  32. package/dist/vite-plugin-upstart-editor/runtime/types.d.ts.map +1 -1
  33. package/dist/vite-plugin-upstart-editor/runtime/utils.js.map +1 -1
  34. package/dist/vite-plugin-upstart-theme.d.ts +3 -3
  35. package/dist/vite-plugin-upstart-theme.d.ts.map +1 -1
  36. package/dist/vite-plugin-upstart-theme.js +2 -2
  37. package/dist/vite-plugin-upstart-theme.js.map +1 -1
  38. package/package.json +7 -7
  39. package/src/tests/vite-plugin-upstart-attrs.test.ts +298 -37
  40. package/src/upstart-editor-api.ts +71 -0
  41. package/src/vite-plugin-upstart-attrs.ts +293 -5
  42. package/src/vite-plugin-upstart-editor/plugin.ts +11 -1
  43. package/src/vite-plugin-upstart-editor/runtime/click-handler.ts +35 -21
  44. package/src/vite-plugin-upstart-editor/runtime/index.ts +21 -1
  45. package/src/vite-plugin-upstart-editor/runtime/text-editor.ts +260 -41
  46. package/src/vite-plugin-upstart-editor/runtime/types.ts +17 -4
  47. package/src/vite-plugin-upstart-theme.ts +4 -1
  48. package/dist/src/vite-plugin-upstart-editor/runtime/state.d.ts.map +0 -1
  49. package/dist/src/vite-plugin-upstart-editor/runtime/state.js.map +0 -1
  50. /package/dist/{src/vite-plugin-upstart-editor → vite-plugin-upstart-editor}/runtime/state.js +0 -0
@@ -16,6 +16,47 @@ const InlineDocument = Node.create({
16
16
  content: "inline*",
17
17
  });
18
18
 
19
+ /**
20
+ * An atomic inline node that represents an i18n template variable like {{year}}.
21
+ * It is displayed as a grayed non-editable chip showing the resolved value.
22
+ * renderText() returns {{varName}} so getText() serialises back to the raw template.
23
+ */
24
+ const TemplateVariable = Node.create({
25
+ name: "templateVariable",
26
+ group: "inline",
27
+ inline: true,
28
+ atom: true,
29
+
30
+ addAttributes() {
31
+ return {
32
+ varName: { default: "" },
33
+ value: { default: "" },
34
+ };
35
+ },
36
+
37
+ parseHTML() {
38
+ return [{ tag: "span[data-tpl-var]" }];
39
+ },
40
+
41
+ renderHTML({ node }) {
42
+ return [
43
+ "span",
44
+ {
45
+ "data-tpl-var": node.attrs.varName,
46
+ contenteditable: "false",
47
+ style:
48
+ "opacity:0.5;background:rgba(0,0,0,0.08);border-radius:3px;padding:0 3px;" +
49
+ "font-family:monospace;font-size:0.875em;cursor:default;user-select:none;",
50
+ },
51
+ node.attrs.value || `{{${node.attrs.varName}}}`,
52
+ ];
53
+ },
54
+
55
+ renderText({ node }) {
56
+ return `{{${node.attrs.varName}}}`;
57
+ },
58
+ });
59
+
19
60
  /**
20
61
  * Remaps Enter to insert a <br> (hard break) instead of creating a new paragraph.
21
62
  * Used in inline-rich mode where block nodes are not allowed.
@@ -36,8 +77,57 @@ const DEFAULT_OPTIONS: Required<UpstartEditorOptions> = {
36
77
  bubbleMenu: true,
37
78
  placeholder: "Start typing...",
38
79
  autoSaveDelay: 1000,
80
+ getRawI18nTemplate: () => undefined,
39
81
  };
40
82
 
83
+ /**
84
+ * Parse a raw i18n template (e.g. "Copyright {{year}}") together with the
85
+ * already-rendered text (e.g. "Copyright 2026") and produce a TipTap JSON
86
+ * document where variable tokens become TemplateVariable nodes.
87
+ */
88
+ function buildI18nContent(rawTemplate: string, renderedText: string): object {
89
+ const VAR_RE = /\{\{(\w+)\}\}/g;
90
+ type Segment = { type: "text"; text: string } | { type: "var"; varName: string };
91
+ const segments: Segment[] = [];
92
+
93
+ let lastIndex = 0;
94
+ let m: RegExpExecArray | null;
95
+ while ((m = VAR_RE.exec(rawTemplate)) !== null) {
96
+ if (m.index > lastIndex) segments.push({ type: "text", text: rawTemplate.slice(lastIndex, m.index) });
97
+ segments.push({ type: "var", varName: m[1] });
98
+ lastIndex = m.index + m[0].length;
99
+ }
100
+ if (lastIndex < rawTemplate.length) segments.push({ type: "text", text: rawTemplate.slice(lastIndex) });
101
+
102
+ // Build a regex over the rendered text to capture variable values
103
+ const escRe = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
104
+ const regexParts = segments.map((s) => (s.type === "text" ? escRe(s.text) : "(.+?)"));
105
+ const fullRegex = new RegExp("^" + regexParts.join("") + "$");
106
+ const varSegments = segments.filter((s): s is Extract<Segment, { type: "var" }> => s.type === "var");
107
+
108
+ const varValues: Record<string, string> = {};
109
+ const match = renderedText.match(fullRegex);
110
+ if (match) {
111
+ varSegments.forEach((seg, i) => {
112
+ varValues[seg.varName] = match[i + 1] ?? `{{${seg.varName}}}`;
113
+ });
114
+ } else {
115
+ varSegments.forEach((seg) => {
116
+ varValues[seg.varName] = `{{${seg.varName}}}`;
117
+ });
118
+ }
119
+
120
+ const inlineNodes = segments
121
+ .map((s) =>
122
+ s.type === "text"
123
+ ? { type: "text", text: s.text }
124
+ : { type: "templateVariable", attrs: { varName: s.varName, value: varValues[s.varName] } },
125
+ )
126
+ .filter((n) => n.type !== "text" || (n as any).text !== "");
127
+
128
+ return { type: "doc", content: [{ type: "paragraph", content: inlineNodes }] };
129
+ }
130
+
41
131
  const activeEditors = new Map<string, EditorInstance>();
42
132
  let i18nSyncInProgress = false;
43
133
  const styleCache = new WeakMap<
@@ -103,18 +193,16 @@ function injectEditorStyles(): void {
103
193
  * Activate editors on all editable elements. Safe to call multiple times.
104
194
  */
105
195
  export function activateAllEditors(): void {
106
- try {
107
- cleanupOrphanedEditors();
108
- const editables = document.querySelectorAll<HTMLElement>('[data-upstart-editable-text="true"]');
109
- editables.forEach((element) => setupEditableElement(element, resolvedOptions));
110
- console.log("[Upstart Editor] Text editors activated");
111
- } catch (error) {
112
- console.error("[Upstart Editor] Failed to activate text editors:", error);
113
- sendToParent({
114
- type: "editor-error",
115
- error: error instanceof Error ? error.message : "Unknown error",
116
- });
117
- }
196
+ cleanupOrphanedEditors();
197
+ const editables = document.querySelectorAll<HTMLElement>('[data-upstart-editable-text="true"]');
198
+ editables.forEach((element) => {
199
+ try {
200
+ setupEditableElement(element, resolvedOptions);
201
+ } catch (error) {
202
+ console.error("[Upstart Editor] Failed to activate element:", element.dataset.upstartHash, error);
203
+ }
204
+ });
205
+ console.log("[Upstart Editor] Text editors activated");
118
206
  }
119
207
 
120
208
  /**
@@ -141,7 +229,14 @@ function activateEditor(element: HTMLElement, hash: string, options: Required<Up
141
229
  const mode = getEditorMode(element, options);
142
230
 
143
231
  let editor: Editor;
232
+
144
233
  switch (mode) {
234
+ case "direct":
235
+ editor = createDirectEditor(element, hash, options);
236
+ break;
237
+ case "rich-panel":
238
+ editor = createRichPanelEditor(element, hash, options);
239
+ break;
145
240
  case "block-rich":
146
241
  editor = createRichTextEditor(element, hash, options);
147
242
  break;
@@ -153,8 +248,6 @@ function activateEditor(element: HTMLElement, hash: string, options: Required<Up
153
248
  break;
154
249
  }
155
250
 
156
- // Restore text rendering on ProseMirror (overrides inherited font-size: 0 etc.)
157
-
158
251
  // Mark element — triggers CSS rules that hide original content
159
252
  element.dataset.upstartEditorActive = "true";
160
253
 
@@ -167,16 +260,42 @@ function createPlainTextEditor(
167
260
  hash: string,
168
261
  options: Required<UpstartEditorOptions>,
169
262
  ): Editor {
170
- const content = element.textContent ?? "";
171
- element.textContent = ""; // Clear the element first! (same as rich text editors)
263
+ const renderedText = element.textContent ?? "";
264
+
265
+ let content: string | object = renderedText;
266
+ const extraExtensions: ReturnType<typeof Node.create>[] = [];
267
+
268
+ // Mixed-text: JSXText + expression chips (e.g. © {year} Some text)
269
+ const mixedTemplate = element.dataset.upstartMixedTemplate;
270
+ if (mixedTemplate) {
271
+ content = buildI18nContent(mixedTemplate, renderedText);
272
+ extraExtensions.push(TemplateVariable);
273
+ } else {
274
+ // Check for i18n template variables (e.g. data-i18n-values="year,month")
275
+ const i18nValueKeys = element.dataset.i18nValues?.split(",").filter(Boolean) ?? [];
276
+ if (i18nValueKeys.length > 0) {
277
+ const i18nAttr = element.dataset.upstartI18n;
278
+ if (i18nAttr) {
279
+ const colonIdx = i18nAttr.indexOf(":");
280
+ const namespace = colonIdx >= 0 ? i18nAttr.slice(0, colonIdx) : "translation";
281
+ const key = colonIdx >= 0 ? i18nAttr.slice(colonIdx + 1) : i18nAttr;
282
+ const rawTemplate = options.getRawI18nTemplate(namespace, key);
283
+ if (rawTemplate) {
284
+ content = buildI18nContent(rawTemplate, renderedText);
285
+ extraExtensions.push(TemplateVariable);
286
+ }
287
+ }
288
+ }
289
+ }
290
+
291
+ element.textContent = "";
172
292
  let hasChanged = false;
173
293
 
174
294
  const editor = new Editor({
175
295
  element,
176
296
  extensions: [
177
- InlineDocument,
297
+ ...extraExtensions,
178
298
  StarterKit.configure({
179
- document: false,
180
299
  heading: false,
181
300
  bold: false,
182
301
  italic: false,
@@ -198,11 +317,9 @@ function createPlainTextEditor(
198
317
  class: "upstart-editor-active",
199
318
  },
200
319
  },
201
- onUpdate: ({ editor: e }) => {
320
+ onUpdate: () => {
202
321
  if (i18nSyncInProgress) return;
203
322
  hasChanged = true;
204
- // const content = e.getText();
205
- // debouncedSave(hash, content, options.autoSaveDelay);
206
323
  syncI18nSiblings(hash);
207
324
  },
208
325
  onBlur: ({ editor: e }) => {
@@ -249,11 +366,9 @@ function createRichTextEditor(
249
366
  class: "upstart-editor-active",
250
367
  },
251
368
  },
252
- onUpdate: ({ editor: e }) => {
369
+ onUpdate: () => {
253
370
  if (i18nSyncInProgress) return;
254
371
  hasChanged = true;
255
- // const content = e.getHTML();
256
- // debouncedSave(hash, content, options.autoSaveDelay);
257
372
  syncI18nSiblings(hash);
258
373
  },
259
374
  onBlur: ({ editor: e }) => {
@@ -315,11 +430,9 @@ function createInlineRichTextEditor(
315
430
  class: "upstart-editor-active",
316
431
  },
317
432
  },
318
- onUpdate: ({ editor: e }) => {
433
+ onUpdate: () => {
319
434
  if (i18nSyncInProgress) return;
320
435
  hasChanged = true;
321
- // const content = e.getHTML();
322
- // debouncedSave(hash, content, options.autoSaveDelay);
323
436
  syncI18nSiblings(hash);
324
437
  },
325
438
  onBlur: ({ editor: e }) => {
@@ -336,9 +449,104 @@ function createInlineRichTextEditor(
336
449
  return editor;
337
450
  }
338
451
 
452
+ function createDirectEditor(
453
+ element: HTMLElement,
454
+ hash: string,
455
+ options: Required<UpstartEditorOptions>,
456
+ ): Editor {
457
+ const content = element.innerHTML;
458
+ element.innerHTML = "";
459
+ let hasChanged = false;
460
+
461
+ const bubbleMenuElement = createBubbleMenuElement("inline");
462
+ const extensions: (Extension | ReturnType<typeof Node.create>)[] = [
463
+ EnterHardBreak,
464
+ StarterKit.configure({
465
+ heading: false,
466
+ blockquote: false,
467
+ bulletList: false,
468
+ orderedList: false,
469
+ listItem: false,
470
+ codeBlock: false,
471
+ horizontalRule: false,
472
+ }),
473
+ Placeholder.configure({ placeholder: "Click to edit..." }),
474
+ ];
475
+
476
+ if (options.bubbleMenu) {
477
+ extensions.push(BubbleMenu.configure({ element: bubbleMenuElement }));
478
+ }
479
+
480
+ const editor = new Editor({
481
+ element,
482
+ extensions,
483
+ content,
484
+ editorProps: { attributes: { class: "upstart-editor-active" } },
485
+ onUpdate: () => {
486
+ hasChanged = true;
487
+ },
488
+ onBlur: ({ editor: e }) => {
489
+ if (!hasChanged) return;
490
+ hasChanged = false;
491
+ // Strip the outer <p> that TipTap adds when using default document schema
492
+ saveText(hash, e.getHTML().replace(/^<p>([\s\S]*)<\/p>$/, "$1"));
493
+ },
494
+ });
495
+
496
+ if (options.bubbleMenu) {
497
+ wireBubbleMenu(bubbleMenuElement, editor);
498
+ }
499
+
500
+ return editor;
501
+ }
502
+
503
+ function createRichPanelEditor(
504
+ element: HTMLElement,
505
+ hash: string,
506
+ options: Required<UpstartEditorOptions>,
507
+ ): Editor {
508
+ const content = element.innerHTML;
509
+ element.innerHTML = "";
510
+ let hasChanged = false;
511
+
512
+ const bubbleMenuElement = createBubbleMenuElement("inline");
513
+ const extensions: Extension[] = [StarterKit, Placeholder.configure({ placeholder: options.placeholder })];
514
+
515
+ if (options.bubbleMenu) {
516
+ extensions.push(BubbleMenu.configure({ element: bubbleMenuElement }));
517
+ }
518
+
519
+ const editor = new Editor({
520
+ element,
521
+ extensions,
522
+ content,
523
+ editorProps: { attributes: { class: "upstart-editor-active" } },
524
+ onUpdate: () => {
525
+ hasChanged = true;
526
+ },
527
+ onBlur: ({ editor: e }) => {
528
+ if (!hasChanged) return;
529
+ hasChanged = false;
530
+ saveText(hash, e.getHTML());
531
+ },
532
+ });
533
+
534
+ if (options.bubbleMenu) {
535
+ wireBubbleMenu(bubbleMenuElement, editor);
536
+ }
537
+
538
+ return editor;
539
+ }
540
+
339
541
  function getEditorMode(element: HTMLElement, options: Required<UpstartEditorOptions>): TextEditorMode {
340
542
  const modeOverride = element.dataset.upstartEditableTextMode as TextEditorMode | undefined;
341
- if (modeOverride === "plain" || modeOverride === "inline-rich" || modeOverride === "block-rich") {
543
+ if (
544
+ modeOverride === "plain" ||
545
+ modeOverride === "inline-rich" ||
546
+ modeOverride === "block-rich" ||
547
+ modeOverride === "direct" ||
548
+ modeOverride === "rich-panel"
549
+ ) {
342
550
  return modeOverride;
343
551
  }
344
552
 
@@ -408,17 +616,27 @@ function saveText(hash: string, newText: string): void {
408
616
  try {
409
617
  const instance = activeEditors.get(hash);
410
618
  const dataset = instance?.element.dataset ?? {};
411
- const [namespace, key] = dataset.upstartI18n?.split(":") ?? [];
412
- sendToParent({
413
- type: "text-edit",
414
- payload: {
415
- action: "editText",
416
- content: newText,
417
- namespace,
418
- key,
419
- language: document.documentElement.lang,
420
- },
421
- });
619
+
620
+ // direct/rich-panel always go via editTextDirect; plain goes via editTextDirect when a
621
+ // registry id is present (mixed-text), and via editText (i18n) otherwise.
622
+ if (instance?.mode === "direct" || instance?.mode === "rich-panel" || dataset.upstartId) {
623
+ sendToParent({
624
+ type: "text-edit",
625
+ payload: { action: "editTextDirect", id: dataset.upstartId!, content: newText },
626
+ });
627
+ } else {
628
+ const [namespace, key] = dataset.upstartI18n?.split(":") ?? [];
629
+ sendToParent({
630
+ type: "text-edit",
631
+ payload: {
632
+ action: "editText",
633
+ content: newText,
634
+ namespace,
635
+ key,
636
+ language: document.documentElement.lang,
637
+ },
638
+ });
639
+ }
422
640
 
423
641
  console.log("[Upstart Editor] Text save message sent:", hash);
424
642
  } catch (error) {
@@ -436,7 +654,8 @@ function destroyEditor(hash: string): void {
436
654
  return;
437
655
  }
438
656
 
439
- const finalContent = instance.mode === "plain" ? instance.editor.getText() : instance.editor.getHTML();
657
+ const isPlainMode = instance.mode === "plain";
658
+ const finalContent = isPlainMode ? instance.editor.getText() : instance.editor.getHTML();
440
659
 
441
660
  instance.editor.destroy();
442
661
 
@@ -448,7 +667,7 @@ function destroyEditor(hash: string): void {
448
667
  delete instance.element.dataset.upstartEditorActive;
449
668
 
450
669
  // Update element content with the final edited text
451
- if (instance.mode === "plain") {
670
+ if (isPlainMode) {
452
671
  instance.element.textContent = finalContent;
453
672
  } else {
454
673
  instance.element.innerHTML = finalContent;
@@ -1,5 +1,5 @@
1
1
  import type { Editor } from "@tiptap/core";
2
- import type { PayloadEditText } from "~/upstart-editor-api";
2
+ import type { PayloadEditText, PayloadEditTextDirect } from "~/upstart-editor-api";
3
3
 
4
4
  /**
5
5
  * Editor mode
@@ -8,8 +8,13 @@ export type EditorMode = "preview" | "edit";
8
8
 
9
9
  /**
10
10
  * Text editor mode: determines schema constraints and bubble menu options.
11
+ * - block-rich: inline TipTap rich text (block-level elements: p, div, article…)
12
+ * - inline-rich: inline TipTap rich text constrained to inline nodes (spans, headings…)
13
+ * - plain: inline TipTap plain text, no formatting
14
+ * - direct: inline TipTap plain text, saved directly into the TSX source
15
+ * - rich-panel: inline TipTap rich text with bubble menu (block-level, like block-rich)
11
16
  */
12
- export type TextEditorMode = "block-rich" | "inline-rich" | "plain";
17
+ export type TextEditorMode = "block-rich" | "inline-rich" | "plain" | "direct" | "rich-panel";
13
18
 
14
19
  /**
15
20
  * Element bounds used for UI positioning.
@@ -37,7 +42,7 @@ export interface EditorInstance {
37
42
  * Messages sent from iframe to parent editor.
38
43
  */
39
44
  export type EditorMessage =
40
- | { type: "text-edit"; payload: PayloadEditText }
45
+ | { type: "text-edit"; payload: PayloadEditText | PayloadEditTextDirect }
41
46
  | { type: "editor-ready" }
42
47
  | { type: "editor-navigated" }
43
48
  | { type: "scroll-position"; x: number; y: number }
@@ -53,6 +58,7 @@ export type EditorMessage =
53
58
  recordId?: string;
54
59
  themeColors?: Record<string, string>;
55
60
  bounds: ElementBounds;
61
+ viewportWidth?: number;
56
62
  };
57
63
 
58
64
  /**
@@ -60,7 +66,7 @@ export type EditorMessage =
60
66
  */
61
67
  export type ParentMessage =
62
68
  | { type: "set-mode"; mode: EditorMode }
63
- | { type: "preview-classname"; classNameId: string; className: string }
69
+ | { type: "preview-classname"; classNameId: string; className: string; previewCSS?: string }
64
70
  | { type: "request-scroll-position" }
65
71
  | { type: "restore-scroll-position"; x: number; y: number };
66
72
 
@@ -122,6 +128,13 @@ export interface UpstartEditorOptions {
122
128
  * @default 1000
123
129
  */
124
130
  autoSaveDelay?: number;
131
+
132
+ /**
133
+ * Callback to retrieve the raw (un-interpolated) i18n template string for a given
134
+ * namespace + key, e.g. "Copyright {{year}}". Used to render template variables as
135
+ * non-editable atoms inside i18n text editors.
136
+ */
137
+ getRawI18nTemplate?: (namespace: string, key: string) => string | undefined;
125
138
  }
126
139
 
127
140
  /**
@@ -77,7 +77,10 @@ function generateFontsCSS(
77
77
  const families = Array.from(allFonts.values()).map((font) => {
78
78
  const name = font.family.replace(/ /g, "+");
79
79
  if (font.weights && font.weights.length > 1 && font.weights[0] !== font.weights.at(-1)) {
80
- return `family=${name}:wght@${font.weights[0]}..${font.weights.at(-1)}`;
80
+ // Take min weight and max weight
81
+ const minWeight = Math.min(...font.weights);
82
+ const maxWeight = Math.max(...font.weights);
83
+ return `family=${name}:wght@${minWeight}..${maxWeight}`;
81
84
  }
82
85
  return `family=${name}`;
83
86
  });
@@ -1 +0,0 @@
1
- {"version":3,"file":"state.d.ts","names":[],"sources":["../../../../src/vite-plugin-upstart-editor/runtime/state.ts"],"mappings":";;;;;AAOA;iBAAgB,cAAA,CAAA,GAAkB,UAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"state.js","names":[],"sources":["../../../../src/vite-plugin-upstart-editor/runtime/state.ts"],"sourcesContent":["import type { EditorMode } from \"./types.js\";\n\nlet currentMode: EditorMode = \"preview\";\n\n/**\n * Get the current editor mode.\n */\nexport function getCurrentMode(): EditorMode {\n return currentMode;\n}\n\n/**\n * Set the current editor mode (internal use only).\n */\nexport function setCurrentMode(mode: EditorMode): void {\n currentMode = mode;\n}\n"],"mappings":";AAEA,IAAI,cAA0B;;;;AAK9B,SAAgB,iBAA6B;AAC3C,QAAO;;;;;AAMT,SAAgB,eAAe,MAAwB;AACrD,eAAc"}