@motion-proto/live-tokens 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +50 -29
  2. package/dist-plugin/index.cjs +177 -125
  3. package/dist-plugin/index.d.cts +3 -2
  4. package/dist-plugin/index.d.ts +3 -2
  5. package/dist-plugin/index.js +177 -125
  6. package/package.json +4 -1
  7. package/src/editor/component-editor/BadgeEditor.svelte +44 -42
  8. package/src/editor/component-editor/ButtonEditor.svelte +224 -0
  9. package/src/editor/component-editor/CollapsibleSectionEditor.svelte +1 -7
  10. package/src/editor/component-editor/CornerBadgeEditor.svelte +44 -34
  11. package/src/editor/component-editor/ImageLightboxEditor.svelte +58 -0
  12. package/src/editor/component-editor/InputEditor.svelte +272 -0
  13. package/src/editor/component-editor/NotificationEditor.svelte +44 -65
  14. package/src/editor/component-editor/ProgressBarEditor.svelte +71 -87
  15. package/src/editor/component-editor/SegmentedControlEditor.svelte +98 -37
  16. package/src/editor/component-editor/SideNavigationEditor.svelte +342 -0
  17. package/src/editor/component-editor/registry.ts +35 -2
  18. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +3 -2
  19. package/src/editor/component-editor/scaffolding/StateBlock.svelte +9 -10
  20. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +60 -36
  21. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +38 -1
  22. package/src/editor/component-editor/scaffolding/buildTypeGroupTokens.ts +1 -1
  23. package/src/editor/component-editor/scaffolding/siblings.ts +2 -2
  24. package/src/editor/component-editor/scaffolding/types.ts +2 -1
  25. package/src/editor/core/components/componentConfigService.ts +7 -6
  26. package/src/editor/core/manifests/manifestService.ts +5 -4
  27. package/src/editor/core/storage/apiBase.ts +15 -0
  28. package/src/editor/core/storage/files/versionedFileResourceClient.ts +1 -1
  29. package/src/editor/core/themes/migrations/2026-05-24-collapsiblesection-drop-active-state.ts +28 -0
  30. package/src/editor/core/themes/migrations/2026-05-24-progressbar-collapse-variants.ts +41 -0
  31. package/src/editor/core/themes/migrations/2026-05-24-promote-state-shared-tokens.ts +59 -0
  32. package/src/editor/core/themes/migrations/2026-05-24-segmentedcontrol-divider-inset.ts +29 -0
  33. package/src/editor/core/themes/migrations/2026-05-25-cornerbadge-flatten-variants.ts +46 -0
  34. package/src/editor/core/themes/migrations/index.ts +10 -0
  35. package/src/editor/core/themes/themeInit.ts +3 -2
  36. package/src/editor/core/themes/themeService.ts +3 -2
  37. package/src/editor/ui/UIEasingSelector.svelte +240 -0
  38. package/src/editor/ui/variantScales.ts +34 -0
  39. package/src/system/components/Button.svelte +34 -85
  40. package/src/system/components/CollapsibleSection.svelte +1 -48
  41. package/src/system/components/CornerBadge.svelte +72 -138
  42. package/src/system/components/ImageLightbox.svelte +578 -0
  43. package/src/system/components/Input.svelte +387 -0
  44. package/src/system/components/ProgressBar.svelte +62 -258
  45. package/src/system/components/SegmentedControl.svelte +81 -15
  46. package/src/system/components/SideNavigation.svelte +777 -0
  47. package/src/system/styles/tokens.css +43 -0
  48. package/src/system/styles/tokens.generated.css +4 -183
  49. package/src/editor/component-editor/StandardButtonsEditor.svelte +0 -190
@@ -1,6 +1,6 @@
1
1
  // vite-plugin/themeFileApi.ts
2
- import fs2 from "fs";
3
- import path2 from "path";
2
+ import fs3 from "fs";
3
+ import path3 from "path";
4
4
 
5
5
  // src/editor/core/themes/parsers/globalRootBlock.ts
6
6
  function extractGlobalRootBody(source) {
@@ -520,18 +520,63 @@ function nextAvailableName(exists, baseName, maxAttempts = 1e3) {
520
520
  throw new Error(`Could not allocate a non-colliding name for "${baseName}"`);
521
521
  }
522
522
 
523
+ // vite-plugin/files/dataPaths.ts
524
+ import fs2 from "fs";
525
+ import path2 from "path";
526
+ var DEFAULT_DATA_DIR = "src/live-tokens/data";
527
+ var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
528
+ "dataDir",
529
+ "themesDir",
530
+ "componentConfigsDir",
531
+ "manifestsDir"
532
+ ]);
533
+ var cached = null;
534
+ function readLiveTokensConfig() {
535
+ if (cached) return cached;
536
+ try {
537
+ const configPath = path2.resolve("live-tokens.config.json");
538
+ if (!fs2.existsSync(configPath)) return cached = {};
539
+ const parsed = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
540
+ if (!parsed || typeof parsed !== "object") return cached = {};
541
+ const unknown = Object.keys(parsed).filter(
542
+ (k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
543
+ );
544
+ if (unknown.length > 0) {
545
+ console.warn(
546
+ `[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
547
+ );
548
+ }
549
+ cached = parsed;
550
+ return cached;
551
+ } catch {
552
+ return cached = {};
553
+ }
554
+ }
555
+ function resolveDataDirs(opts = {}) {
556
+ const fileConfig = readLiveTokensConfig();
557
+ const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
558
+ const dataDir = path2.resolve(dataDirRaw);
559
+ const sub = (name) => path2.resolve(dataDir, name);
560
+ return {
561
+ dataDir,
562
+ themesDir: opts.themesDir ? path2.resolve(opts.themesDir) : fileConfig.themesDir ? path2.resolve(fileConfig.themesDir) : sub("themes"),
563
+ componentConfigsDir: opts.componentConfigsDir ? path2.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? path2.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
564
+ manifestsDir: opts.manifestsDir ? path2.resolve(opts.manifestsDir) : fileConfig.manifestsDir ? path2.resolve(fileConfig.manifestsDir) : sub("manifests")
565
+ };
566
+ }
567
+
523
568
  // vite-plugin/themeFileApi.ts
524
569
  import { fileURLToPath } from "url";
525
570
  var PKG_VERSION = (() => {
526
571
  try {
527
- let dir = path2.dirname(fileURLToPath(import.meta.url));
572
+ let dir = path3.dirname(fileURLToPath(import.meta.url));
528
573
  for (let i = 0; i < 4; i++) {
529
- const p = path2.join(dir, "package.json");
530
- if (fs2.existsSync(p)) {
531
- const json = JSON.parse(fs2.readFileSync(p, "utf-8"));
574
+ const p = path3.join(dir, "package.json");
575
+ if (fs3.existsSync(p)) {
576
+ const json = JSON.parse(fs3.readFileSync(p, "utf-8"));
532
577
  if (json?.name === "@motion-proto/live-tokens") return json.version ?? "";
533
578
  }
534
- const up = path2.dirname(dir);
579
+ const up = path3.dirname(dir);
535
580
  if (up === dir) break;
536
581
  dir = up;
537
582
  }
@@ -540,15 +585,21 @@ var PKG_VERSION = (() => {
540
585
  return "";
541
586
  })();
542
587
  function themeFileApi(opts) {
543
- const THEMES_DIR = path2.resolve(opts.themesDir);
544
- const CSS_PATH = path2.resolve(opts.tokensCssPath);
545
- const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? path2.resolve(opts.tokensGeneratedCssPath) : path2.join(path2.dirname(CSS_PATH), "tokens.generated.css");
546
- const FONTS_CSS_PATH = opts.fontsCssPath ? path2.resolve(opts.fontsCssPath) : path2.join(path2.dirname(CSS_PATH), "fonts.css");
547
- const API_BASE = opts.apiBase ?? "/api";
548
- const COMPONENT_CONFIGS_DIR = opts.componentConfigsDir ? path2.resolve(opts.componentConfigsDir) : path2.resolve("component-configs");
549
- const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? path2.resolve(opts.componentsSrcDir) : path2.resolve("src/system/components");
550
- const MANIFESTS_DIR = opts.manifestsDir ? path2.resolve(opts.manifestsDir) : path2.resolve("manifests");
551
- const LEGACY_PRESETS_DIR = path2.resolve("presets");
588
+ const dataDirs = resolveDataDirs({
589
+ dataDir: opts.dataDir,
590
+ themesDir: opts.themesDir,
591
+ componentConfigsDir: opts.componentConfigsDir,
592
+ manifestsDir: opts.manifestsDir
593
+ });
594
+ const THEMES_DIR = dataDirs.themesDir;
595
+ const COMPONENT_CONFIGS_DIR = dataDirs.componentConfigsDir;
596
+ const MANIFESTS_DIR = dataDirs.manifestsDir;
597
+ const CSS_PATH = path3.resolve(opts.tokensCssPath);
598
+ const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? path3.resolve(opts.tokensGeneratedCssPath) : path3.join(path3.dirname(CSS_PATH), "tokens.generated.css");
599
+ const FONTS_CSS_PATH = opts.fontsCssPath ? path3.resolve(opts.fontsCssPath) : path3.join(path3.dirname(CSS_PATH), "fonts.css");
600
+ const API_BASE = opts.apiBase ?? "/api/live-tokens";
601
+ const COMPONENTS_SRC_DIR = opts.componentsSrcDir ? path3.resolve(opts.componentsSrcDir) : path3.resolve("src/system/components");
602
+ const LEGACY_PRESETS_DIR = path3.resolve("presets");
552
603
  const themesResource = versionedFileResourceServer({
553
604
  dir: THEMES_DIR
554
605
  });
@@ -556,7 +607,7 @@ function themeFileApi(opts) {
556
607
  function componentResource(comp) {
557
608
  let r = componentResourceCache.get(comp);
558
609
  if (!r) {
559
- r = versionedFileResourceServer({ dir: path2.join(COMPONENT_CONFIGS_DIR, comp) });
610
+ r = versionedFileResourceServer({ dir: path3.join(COMPONENT_CONFIGS_DIR, comp) });
560
611
  componentResourceCache.set(comp, r);
561
612
  }
562
613
  return r;
@@ -564,7 +615,7 @@ function themeFileApi(opts) {
564
615
  const manifestsResource = versionedFileResourceServer({ dir: MANIFESTS_DIR });
565
616
  function ensureThemesDir() {
566
617
  themesResource.ensureDir();
567
- if (!fs2.existsSync(path2.join(THEMES_DIR, "default.json"))) {
618
+ if (!fs3.existsSync(path3.join(THEMES_DIR, "default.json"))) {
568
619
  const defaultTheme = {
569
620
  name: "Default Theme",
570
621
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -572,7 +623,7 @@ function themeFileApi(opts) {
572
623
  editorConfigs: {},
573
624
  cssVariables: {}
574
625
  };
575
- fs2.writeFileSync(path2.join(THEMES_DIR, "default.json"), JSON.stringify(defaultTheme, null, 2));
626
+ fs3.writeFileSync(path3.join(THEMES_DIR, "default.json"), JSON.stringify(defaultTheme, null, 2));
576
627
  }
577
628
  themesResource.ensureMeta();
578
629
  }
@@ -637,10 +688,10 @@ function themeFileApi(opts) {
637
688
  lines.push("/* tokens.css holds developer-authored defaults; this file holds editor overrides. */");
638
689
  lines.push("");
639
690
  const productionThemeName = themesResource.getProductionName();
640
- const themePath = path2.join(THEMES_DIR, `${productionThemeName}.json`);
691
+ const themePath = path3.join(THEMES_DIR, `${productionThemeName}.json`);
641
692
  let themeVarCount = 0;
642
- if (fs2.existsSync(themePath)) {
643
- const themeData = JSON.parse(fs2.readFileSync(themePath, "utf-8"));
693
+ if (fs3.existsSync(themePath)) {
694
+ const themeData = JSON.parse(fs3.readFileSync(themePath, "utf-8"));
644
695
  const cssVars = { ...themeData.cssVariables || {} };
645
696
  Object.assign(cssVars, palettesToVars(themeData.editorConfigs ?? {}));
646
697
  const resolvedFontVars = resolveFontStacks(themeData);
@@ -659,7 +710,7 @@ function themeFileApi(opts) {
659
710
  }
660
711
  }
661
712
  let componentOverrideCount = 0;
662
- if (fs2.existsSync(COMPONENT_CONFIGS_DIR)) {
713
+ if (fs3.existsSync(COMPONENT_CONFIGS_DIR)) {
663
714
  const blocks = [];
664
715
  for (const comp of listComponentNames()) {
665
716
  const prod = componentResource(comp).getProductionName();
@@ -693,21 +744,21 @@ function themeFileApi(opts) {
693
744
  lines.push("");
694
745
  }
695
746
  }
696
- if (!fs2.existsSync(path2.dirname(GENERATED_CSS_PATH))) {
697
- fs2.mkdirSync(path2.dirname(GENERATED_CSS_PATH), { recursive: true });
747
+ if (!fs3.existsSync(path3.dirname(GENERATED_CSS_PATH))) {
748
+ fs3.mkdirSync(path3.dirname(GENERATED_CSS_PATH), { recursive: true });
698
749
  }
699
- fs2.writeFileSync(GENERATED_CSS_PATH, lines.join("\n"));
750
+ fs3.writeFileSync(GENERATED_CSS_PATH, lines.join("\n"));
700
751
  console.log(
701
- `[regenerateTokensCss] Wrote ${path2.basename(GENERATED_CSS_PATH)} (${themeVarCount} theme vars, ${componentOverrideCount} component overrides)`
752
+ `[regenerateTokensCss] Wrote ${path3.basename(GENERATED_CSS_PATH)} (${themeVarCount} theme vars, ${componentOverrideCount} component overrides)`
702
753
  );
703
754
  }
704
755
  function syncTokensToCss(_fileName) {
705
756
  regenerateTokensCss();
706
757
  }
707
758
  function syncFontsToCss(fileName) {
708
- const themePath = path2.join(THEMES_DIR, `${fileName}.json`);
709
- if (!fs2.existsSync(themePath)) return;
710
- const themeData = JSON.parse(fs2.readFileSync(themePath, "utf-8"));
759
+ const themePath = path3.join(THEMES_DIR, `${fileName}.json`);
760
+ if (!fs3.existsSync(themePath)) return;
761
+ const themeData = JSON.parse(fs3.readFileSync(themePath, "utf-8"));
711
762
  const sources = themeData.fontSources;
712
763
  if (!sources) return;
713
764
  const lines = [];
@@ -731,11 +782,11 @@ function themeFileApi(opts) {
731
782
  lines.push("");
732
783
  }
733
784
  const content = lines.join("\n");
734
- if (!fs2.existsSync(path2.dirname(FONTS_CSS_PATH))) {
735
- fs2.mkdirSync(path2.dirname(FONTS_CSS_PATH), { recursive: true });
785
+ if (!fs3.existsSync(path3.dirname(FONTS_CSS_PATH))) {
786
+ fs3.mkdirSync(path3.dirname(FONTS_CSS_PATH), { recursive: true });
736
787
  }
737
- fs2.writeFileSync(FONTS_CSS_PATH, content);
738
- console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${path2.basename(FONTS_CSS_PATH)}`);
788
+ fs3.writeFileSync(FONTS_CSS_PATH, content);
789
+ console.log(`[syncFontsToCss] Wrote ${sources.length} source(s) into ${path3.basename(FONTS_CSS_PATH)}`);
739
790
  }
740
791
  function extractAliasDeclarations(body) {
741
792
  const aliases = {};
@@ -745,35 +796,35 @@ function themeFileApi(opts) {
745
796
  return aliases;
746
797
  }
747
798
  function componentNameFromFile(filePath) {
748
- return path2.basename(filePath, ".svelte").toLowerCase();
799
+ return path3.basename(filePath, ".svelte").toLowerCase();
749
800
  }
750
801
  function listComponentSourcePaths() {
751
- if (!fs2.existsSync(COMPONENTS_SRC_DIR)) return [];
752
- return fs2.readdirSync(COMPONENTS_SRC_DIR).filter((f) => f.endsWith(".svelte")).map((f) => path2.join(COMPONENTS_SRC_DIR, f));
802
+ if (!fs3.existsSync(COMPONENTS_SRC_DIR)) return [];
803
+ return fs3.readdirSync(COMPONENTS_SRC_DIR).filter((f) => f.endsWith(".svelte")).map((f) => path3.join(COMPONENTS_SRC_DIR, f));
753
804
  }
754
805
  function listComponentNames() {
755
806
  return listComponentSourcePaths().map(componentNameFromFile);
756
807
  }
757
808
  function generateDefaultConfig(comp, sourcePath) {
758
- if (!fs2.existsSync(sourcePath)) return;
809
+ if (!fs3.existsSync(sourcePath)) return;
759
810
  const r = componentResource(comp);
760
811
  r.ensureDir();
761
812
  const defaultPath = r.filePath("default");
762
- const sourceStat = fs2.statSync(sourcePath);
763
- if (fs2.existsSync(defaultPath)) {
764
- const defaultStat = fs2.statSync(defaultPath);
813
+ const sourceStat = fs3.statSync(sourcePath);
814
+ if (fs3.existsSync(defaultPath)) {
815
+ const defaultStat = fs3.statSync(defaultPath);
765
816
  if (defaultStat.mtimeMs >= sourceStat.mtimeMs) return;
766
817
  }
767
- const source = fs2.readFileSync(sourcePath, "utf-8");
818
+ const source = fs3.readFileSync(sourcePath, "utf-8");
768
819
  const body = extractGlobalRootBody(source);
769
820
  const aliases = extractAliasDeclarations(body);
770
821
  const now = (/* @__PURE__ */ new Date()).toISOString();
771
822
  let createdAt = now;
772
823
  let existingUpdatedAt;
773
824
  let existingAliases;
774
- if (fs2.existsSync(defaultPath)) {
825
+ if (fs3.existsSync(defaultPath)) {
775
826
  try {
776
- const existing = JSON.parse(fs2.readFileSync(defaultPath, "utf-8"));
827
+ const existing = JSON.parse(fs3.readFileSync(defaultPath, "utf-8"));
777
828
  if (existing.createdAt) createdAt = existing.createdAt;
778
829
  if (typeof existing.updatedAt === "string") existingUpdatedAt = existing.updatedAt;
779
830
  if (existing.aliases && typeof existing.aliases === "object") {
@@ -792,14 +843,14 @@ function themeFileApi(opts) {
792
843
  };
793
844
  if (aliasesUnchanged && existingUpdatedAt) {
794
845
  const t = /* @__PURE__ */ new Date();
795
- fs2.utimesSync(defaultPath, t, t);
846
+ fs3.utimesSync(defaultPath, t, t);
796
847
  return;
797
848
  }
798
- fs2.writeFileSync(defaultPath, JSON.stringify(defaultConfig, null, 2));
849
+ fs3.writeFileSync(defaultPath, JSON.stringify(defaultConfig, null, 2));
799
850
  }
800
851
  function ensureComponentConfigsDir() {
801
- if (!fs2.existsSync(COMPONENT_CONFIGS_DIR)) {
802
- fs2.mkdirSync(COMPONENT_CONFIGS_DIR, { recursive: true });
852
+ if (!fs3.existsSync(COMPONENT_CONFIGS_DIR)) {
853
+ fs3.mkdirSync(COMPONENT_CONFIGS_DIR, { recursive: true });
803
854
  }
804
855
  for (const sourcePath of listComponentSourcePaths()) {
805
856
  const comp = componentNameFromFile(sourcePath);
@@ -810,14 +861,14 @@ function themeFileApi(opts) {
810
861
  }
811
862
  }
812
863
  function ensureManifestsDir() {
813
- if (!fs2.existsSync(MANIFESTS_DIR) && fs2.existsSync(LEGACY_PRESETS_DIR)) {
814
- fs2.renameSync(LEGACY_PRESETS_DIR, MANIFESTS_DIR);
815
- const legacyProd = path2.join(MANIFESTS_DIR, "_production.json");
816
- if (fs2.existsSync(legacyProd)) fs2.unlinkSync(legacyProd);
864
+ if (!fs3.existsSync(MANIFESTS_DIR) && fs3.existsSync(LEGACY_PRESETS_DIR)) {
865
+ fs3.renameSync(LEGACY_PRESETS_DIR, MANIFESTS_DIR);
866
+ const legacyProd = path3.join(MANIFESTS_DIR, "_production.json");
867
+ if (fs3.existsSync(legacyProd)) fs3.unlinkSync(legacyProd);
817
868
  }
818
869
  manifestsResource.ensureDir();
819
- const defaultPath = path2.join(MANIFESTS_DIR, "default.json");
820
- if (!fs2.existsSync(defaultPath)) {
870
+ const defaultPath = path3.join(MANIFESTS_DIR, "default.json");
871
+ if (!fs3.existsSync(defaultPath)) {
821
872
  const componentConfigs = {};
822
873
  for (const comp of listComponentNames()) {
823
874
  componentConfigs[comp] = componentResource(comp).getActiveName();
@@ -830,30 +881,30 @@ function themeFileApi(opts) {
830
881
  theme: themesResource.getActiveName(),
831
882
  componentConfigs
832
883
  };
833
- fs2.writeFileSync(defaultPath, JSON.stringify(defaultManifest, null, 2));
884
+ fs3.writeFileSync(defaultPath, JSON.stringify(defaultManifest, null, 2));
834
885
  }
835
- if (!fs2.existsSync(manifestsResource.activePath)) {
836
- fs2.writeFileSync(
886
+ if (!fs3.existsSync(manifestsResource.activePath)) {
887
+ fs3.writeFileSync(
837
888
  manifestsResource.activePath,
838
889
  JSON.stringify({ activeFile: "default" })
839
890
  );
840
891
  } else {
841
892
  const activeName = manifestsResource.getActiveName();
842
- if (!fs2.existsSync(manifestsResource.filePath(activeName))) {
893
+ if (!fs3.existsSync(manifestsResource.filePath(activeName))) {
843
894
  manifestsResource.setActiveName("default");
844
895
  }
845
896
  }
846
- const stragglerProd = path2.join(MANIFESTS_DIR, "_production.json");
847
- if (fs2.existsSync(stragglerProd)) fs2.unlinkSync(stragglerProd);
897
+ const stragglerProd = path3.join(MANIFESTS_DIR, "_production.json");
898
+ if (fs3.existsSync(stragglerProd)) fs3.unlinkSync(stragglerProd);
848
899
  }
849
900
  function patchActiveManifest(field, comp, fileName) {
850
901
  const activeFile = manifestsResource.getActiveName();
851
902
  if (activeFile === "default") return false;
852
903
  const manifestPath = manifestsResource.filePath(activeFile);
853
- if (!fs2.existsSync(manifestPath)) return false;
904
+ if (!fs3.existsSync(manifestPath)) return false;
854
905
  let manifest;
855
906
  try {
856
- manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
907
+ manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
857
908
  } catch {
858
909
  return false;
859
910
  }
@@ -864,7 +915,7 @@ function themeFileApi(opts) {
864
915
  manifest.componentConfigs[comp] = fileName;
865
916
  }
866
917
  manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
867
- fs2.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
918
+ fs3.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
868
919
  return true;
869
920
  }
870
921
  function formatAliasGradient(v) {
@@ -896,9 +947,9 @@ function themeFileApi(opts) {
896
947
  }
897
948
  function readComponentConfig(comp, name) {
898
949
  const filePath = componentResource(comp).filePath(name);
899
- if (!fs2.existsSync(filePath)) return null;
950
+ if (!fs3.existsSync(filePath)) return null;
900
951
  try {
901
- return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
952
+ return JSON.parse(fs3.readFileSync(filePath, "utf-8"));
902
953
  } catch {
903
954
  return null;
904
955
  }
@@ -924,9 +975,9 @@ function themeFileApi(opts) {
924
975
  const MANIFEST_BY_NAME_REGEX = new RegExp(`^${escapedBase}/manifests/([a-z0-9\\-_]+)$`);
925
976
  async function handleListThemes(_ctx) {
926
977
  const activeFile = themesResource.getActiveName();
927
- const files = fs2.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
928
- const filePath = path2.join(THEMES_DIR, f);
929
- const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
978
+ const files = fs3.readdirSync(THEMES_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
979
+ const filePath = path3.join(THEMES_DIR, f);
980
+ const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
930
981
  const fileName = f.replace(".json", "");
931
982
  return {
932
983
  name: data.name || fileName,
@@ -940,18 +991,18 @@ function themeFileApi(opts) {
940
991
  async function handleGetActiveTheme({ res }) {
941
992
  const activeFile = themesResource.getActiveName();
942
993
  const filePath = themesResource.filePath(activeFile);
943
- if (!fs2.existsSync(filePath)) {
994
+ if (!fs3.existsSync(filePath)) {
944
995
  jsonResponse(res, 404, { error: "Active theme not found" });
945
996
  return;
946
997
  }
947
- const data = normalizeTheme(JSON.parse(fs2.readFileSync(filePath, "utf-8")));
998
+ const data = normalizeTheme(JSON.parse(fs3.readFileSync(filePath, "utf-8")));
948
999
  data._fileName = activeFile;
949
1000
  jsonResponse(res, 200, data);
950
1001
  }
951
1002
  async function handleSetActiveTheme({ req, res }) {
952
1003
  const body = JSON.parse(await readBody(req));
953
1004
  const fileName = sanitizeFileName(body.name || "default");
954
- if (!fs2.existsSync(themesResource.filePath(fileName))) {
1005
+ if (!fs3.existsSync(themesResource.filePath(fileName))) {
955
1006
  jsonResponse(res, 404, { error: "Theme not found" });
956
1007
  return;
957
1008
  }
@@ -961,11 +1012,11 @@ function themeFileApi(opts) {
961
1012
  async function handleGetProductionTheme({ res }) {
962
1013
  const prodFile = themesResource.getProductionName();
963
1014
  const filePath = themesResource.filePath(prodFile);
964
- if (!fs2.existsSync(filePath)) {
1015
+ if (!fs3.existsSync(filePath)) {
965
1016
  jsonResponse(res, 200, { fileName: prodFile, name: prodFile, cssVariables: {} });
966
1017
  return;
967
1018
  }
968
- const data = normalizeTheme(JSON.parse(fs2.readFileSync(filePath, "utf-8")));
1019
+ const data = normalizeTheme(JSON.parse(fs3.readFileSync(filePath, "utf-8")));
969
1020
  jsonResponse(res, 200, {
970
1021
  fileName: prodFile,
971
1022
  name: data.name || prodFile,
@@ -976,7 +1027,7 @@ function themeFileApi(opts) {
976
1027
  async function handleSetProductionTheme({ req, res }) {
977
1028
  const body = JSON.parse(await readBody(req));
978
1029
  const fileName = sanitizeFileName(body.name || "default");
979
- if (!fs2.existsSync(themesResource.filePath(fileName))) {
1030
+ if (!fs3.existsSync(themesResource.filePath(fileName))) {
980
1031
  jsonResponse(res, 404, { error: "Theme not found" });
981
1032
  return;
982
1033
  }
@@ -992,7 +1043,7 @@ function themeFileApi(opts) {
992
1043
  syncFontsToCss(fileName);
993
1044
  syncComponentsToCss();
994
1045
  patchActiveManifest("theme", null, fileName);
995
- const data = JSON.parse(fs2.readFileSync(themesResource.filePath(fileName), "utf-8"));
1046
+ const data = JSON.parse(fs3.readFileSync(themesResource.filePath(fileName), "utf-8"));
996
1047
  jsonResponse(res, 200, {
997
1048
  ok: true,
998
1049
  fileName,
@@ -1004,11 +1055,11 @@ function themeFileApi(opts) {
1004
1055
  const [fileName] = params;
1005
1056
  const filePath = themesResource.filePath(fileName);
1006
1057
  if (req.method === "GET") {
1007
- if (!fs2.existsSync(filePath)) {
1058
+ if (!fs3.existsSync(filePath)) {
1008
1059
  jsonResponse(res, 404, { error: "Not found" });
1009
1060
  return;
1010
1061
  }
1011
- const data = normalizeTheme(JSON.parse(fs2.readFileSync(filePath, "utf-8")));
1062
+ const data = normalizeTheme(JSON.parse(fs3.readFileSync(filePath, "utf-8")));
1012
1063
  data._fileName = fileName;
1013
1064
  jsonResponse(res, 200, data);
1014
1065
  return;
@@ -1016,15 +1067,15 @@ function themeFileApi(opts) {
1016
1067
  if (req.method === "PUT") {
1017
1068
  const body = JSON.parse(await readBody(req));
1018
1069
  body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1019
- if (fs2.existsSync(filePath)) {
1070
+ if (fs3.existsSync(filePath)) {
1020
1071
  try {
1021
- const existing = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
1072
+ const existing = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
1022
1073
  if (existing.createdAt) body.createdAt = existing.createdAt;
1023
1074
  } catch {
1024
1075
  }
1025
1076
  }
1026
1077
  if (!body.createdAt) body.createdAt = body.updatedAt;
1027
- fs2.writeFileSync(filePath, JSON.stringify(body, null, 2));
1078
+ fs3.writeFileSync(filePath, JSON.stringify(body, null, 2));
1028
1079
  if (fileName === themesResource.getProductionName()) {
1029
1080
  syncTokensToCss(fileName);
1030
1081
  syncFontsToCss(fileName);
@@ -1045,8 +1096,8 @@ function themeFileApi(opts) {
1045
1096
  });
1046
1097
  return;
1047
1098
  }
1048
- if (fs2.existsSync(filePath)) {
1049
- fs2.unlinkSync(filePath);
1099
+ if (fs3.existsSync(filePath)) {
1100
+ fs3.unlinkSync(filePath);
1050
1101
  if (themesResource.getActiveName() === fileName) {
1051
1102
  themesResource.setActiveName("default");
1052
1103
  }
@@ -1083,7 +1134,7 @@ function themeFileApi(opts) {
1083
1134
  const fileName = sanitizeFileName(body.name || "default");
1084
1135
  const r = componentResource(comp);
1085
1136
  const configPath = r.filePath(fileName);
1086
- if (!fs2.existsSync(configPath)) {
1137
+ if (!fs3.existsSync(configPath)) {
1087
1138
  jsonResponse(res, 404, { error: "Config not found" });
1088
1139
  return;
1089
1140
  }
@@ -1108,7 +1159,7 @@ function themeFileApi(opts) {
1108
1159
  const fileName = sanitizeFileName(body.name || "default");
1109
1160
  const r = componentResource(comp);
1110
1161
  const configPath = r.filePath(fileName);
1111
- if (!fs2.existsSync(configPath)) {
1162
+ if (!fs3.existsSync(configPath)) {
1112
1163
  jsonResponse(res, 404, { error: "Config not found" });
1113
1164
  return;
1114
1165
  }
@@ -1136,11 +1187,11 @@ function themeFileApi(opts) {
1136
1187
  const r = componentResource(comp);
1137
1188
  const configPath = r.filePath(name);
1138
1189
  if (req.method === "GET") {
1139
- if (!fs2.existsSync(configPath)) {
1190
+ if (!fs3.existsSync(configPath)) {
1140
1191
  jsonResponse(res, 404, { error: "Not found" });
1141
1192
  return;
1142
1193
  }
1143
- const data = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
1194
+ const data = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
1144
1195
  data._fileName = name;
1145
1196
  jsonResponse(res, 200, data);
1146
1197
  return;
@@ -1154,16 +1205,16 @@ function themeFileApi(opts) {
1154
1205
  body.component = comp;
1155
1206
  body.name = body.name || name;
1156
1207
  body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1157
- if (fs2.existsSync(configPath)) {
1208
+ if (fs3.existsSync(configPath)) {
1158
1209
  try {
1159
- const existing = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
1210
+ const existing = JSON.parse(fs3.readFileSync(configPath, "utf-8"));
1160
1211
  if (existing.createdAt) body.createdAt = existing.createdAt;
1161
1212
  } catch {
1162
1213
  }
1163
1214
  }
1164
1215
  if (!body.createdAt) body.createdAt = body.updatedAt;
1165
1216
  r.ensureDir();
1166
- fs2.writeFileSync(configPath, JSON.stringify(body, null, 2));
1217
+ fs3.writeFileSync(configPath, JSON.stringify(body, null, 2));
1167
1218
  if (r.getProductionName() === name) {
1168
1219
  syncComponentsToCss();
1169
1220
  }
@@ -1175,8 +1226,8 @@ function themeFileApi(opts) {
1175
1226
  jsonResponse(res, 403, { error: "Cannot delete default config" });
1176
1227
  return;
1177
1228
  }
1178
- if (fs2.existsSync(configPath)) {
1179
- fs2.unlinkSync(configPath);
1229
+ if (fs3.existsSync(configPath)) {
1230
+ fs3.unlinkSync(configPath);
1180
1231
  if (r.getActiveName() === name) {
1181
1232
  r.setActiveName("default");
1182
1233
  }
@@ -1192,15 +1243,15 @@ function themeFileApi(opts) {
1192
1243
  async function handleListComponentConfigs({ params, res }) {
1193
1244
  const [comp] = params;
1194
1245
  const r = componentResource(comp);
1195
- if (!fs2.existsSync(r.dir)) {
1246
+ if (!fs3.existsSync(r.dir)) {
1196
1247
  jsonResponse(res, 404, { error: "Component not found" });
1197
1248
  return;
1198
1249
  }
1199
1250
  const activeFile = r.getActiveName();
1200
1251
  const productionFile = r.getProductionName();
1201
- const files = fs2.readdirSync(r.dir).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
1202
- const filePath = path2.join(r.dir, f);
1203
- const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
1252
+ const files = fs3.readdirSync(r.dir).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
1253
+ const filePath = path3.join(r.dir, f);
1254
+ const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
1204
1255
  const fileName = f.replace(".json", "");
1205
1256
  return {
1206
1257
  name: data.name || fileName,
@@ -1214,9 +1265,9 @@ function themeFileApi(opts) {
1214
1265
  }
1215
1266
  async function handleListManifests({ res }) {
1216
1267
  const activeFile = manifestsResource.getActiveName();
1217
- const files = fs2.readdirSync(MANIFESTS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
1218
- const filePath = path2.join(MANIFESTS_DIR, f);
1219
- const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
1268
+ const files = fs3.readdirSync(MANIFESTS_DIR).filter((f) => f.endsWith(".json") && !f.startsWith("_")).map((f) => {
1269
+ const filePath = path3.join(MANIFESTS_DIR, f);
1270
+ const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
1220
1271
  const fileName = f.replace(".json", "");
1221
1272
  return {
1222
1273
  name: data.name || fileName,
@@ -1231,18 +1282,18 @@ function themeFileApi(opts) {
1231
1282
  async function handleGetActiveManifest({ res }) {
1232
1283
  const activeFile = manifestsResource.getActiveName();
1233
1284
  const filePath = manifestsResource.filePath(activeFile);
1234
- if (!fs2.existsSync(filePath)) {
1285
+ if (!fs3.existsSync(filePath)) {
1235
1286
  jsonResponse(res, 404, { error: "Active manifest not found" });
1236
1287
  return;
1237
1288
  }
1238
- const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
1289
+ const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
1239
1290
  data._fileName = activeFile;
1240
1291
  jsonResponse(res, 200, data);
1241
1292
  }
1242
1293
  async function handleSetActiveManifest({ req, res }) {
1243
1294
  const body = JSON.parse(await readBody(req));
1244
1295
  const fileName = sanitizeFileName(body.name || "default");
1245
- if (!fs2.existsSync(manifestsResource.filePath(fileName))) {
1296
+ if (!fs3.existsSync(manifestsResource.filePath(fileName))) {
1246
1297
  jsonResponse(res, 404, { error: "Manifest not found" });
1247
1298
  return;
1248
1299
  }
@@ -1253,11 +1304,11 @@ function themeFileApi(opts) {
1253
1304
  const [fileName] = params;
1254
1305
  const filePath = manifestsResource.filePath(fileName);
1255
1306
  if (req.method === "GET") {
1256
- if (!fs2.existsSync(filePath)) {
1307
+ if (!fs3.existsSync(filePath)) {
1257
1308
  jsonResponse(res, 404, { error: "Not found" });
1258
1309
  return;
1259
1310
  }
1260
- const data = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
1311
+ const data = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
1261
1312
  data._fileName = fileName;
1262
1313
  jsonResponse(res, 200, data);
1263
1314
  return;
@@ -1269,15 +1320,15 @@ function themeFileApi(opts) {
1269
1320
  }
1270
1321
  const body = JSON.parse(await readBody(req));
1271
1322
  body.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1272
- if (fs2.existsSync(filePath)) {
1323
+ if (fs3.existsSync(filePath)) {
1273
1324
  try {
1274
- const existing = JSON.parse(fs2.readFileSync(filePath, "utf-8"));
1325
+ const existing = JSON.parse(fs3.readFileSync(filePath, "utf-8"));
1275
1326
  if (existing.createdAt) body.createdAt = existing.createdAt;
1276
1327
  } catch {
1277
1328
  }
1278
1329
  }
1279
1330
  if (!body.createdAt) body.createdAt = body.updatedAt;
1280
- fs2.writeFileSync(filePath, JSON.stringify(body, null, 2));
1331
+ fs3.writeFileSync(filePath, JSON.stringify(body, null, 2));
1281
1332
  jsonResponse(res, 200, { ok: true, fileName });
1282
1333
  return;
1283
1334
  }
@@ -1286,8 +1337,8 @@ function themeFileApi(opts) {
1286
1337
  jsonResponse(res, 403, { error: "Cannot delete the default manifest" });
1287
1338
  return;
1288
1339
  }
1289
- if (fs2.existsSync(filePath)) {
1290
- fs2.unlinkSync(filePath);
1340
+ if (fs3.existsSync(filePath)) {
1341
+ fs3.unlinkSync(filePath);
1291
1342
  if (manifestsResource.getActiveName() === fileName) {
1292
1343
  manifestsResource.setActiveName("default");
1293
1344
  }
@@ -1299,14 +1350,14 @@ function themeFileApi(opts) {
1299
1350
  async function handleApplyManifest({ params, res }) {
1300
1351
  const [fileName] = params;
1301
1352
  const manifestPath = manifestsResource.filePath(fileName);
1302
- if (!fs2.existsSync(manifestPath)) {
1353
+ if (!fs3.existsSync(manifestPath)) {
1303
1354
  jsonResponse(res, 404, { error: "Manifest not found" });
1304
1355
  return;
1305
1356
  }
1306
- const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
1357
+ const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
1307
1358
  const themeName = sanitizeFileName(manifest.theme || "default");
1308
1359
  const themePath = themesResource.filePath(themeName);
1309
- if (!fs2.existsSync(themePath)) {
1360
+ if (!fs3.existsSync(themePath)) {
1310
1361
  jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
1311
1362
  return;
1312
1363
  }
@@ -1319,7 +1370,7 @@ function themeFileApi(opts) {
1319
1370
  const sanitized = sanitizeFileName(String(configFile) || "default");
1320
1371
  const r = componentResource(comp);
1321
1372
  const cfgPath = r.filePath(sanitized);
1322
- if (!fs2.existsSync(cfgPath)) {
1373
+ if (!fs3.existsSync(cfgPath)) {
1323
1374
  jsonResponse(res, 422, {
1324
1375
  error: `Manifest references missing config: ${comp}/${sanitized}`
1325
1376
  });
@@ -1331,7 +1382,7 @@ function themeFileApi(opts) {
1331
1382
  themesResource.setProductionName(themeName);
1332
1383
  syncTokensToCss(themeName);
1333
1384
  syncFontsToCss(themeName);
1334
- const themeData = normalizeTheme(JSON.parse(fs2.readFileSync(themePath, "utf-8")));
1385
+ const themeData = normalizeTheme(JSON.parse(fs3.readFileSync(themePath, "utf-8")));
1335
1386
  themeData._fileName = themeName;
1336
1387
  for (const [comp, configFile] of apply) {
1337
1388
  const r = componentResource(comp);
@@ -1358,18 +1409,18 @@ function themeFileApi(opts) {
1358
1409
  async function handleExportManifest({ params, res }) {
1359
1410
  const [fileName] = params;
1360
1411
  const manifestPath = manifestsResource.filePath(fileName);
1361
- if (!fs2.existsSync(manifestPath)) {
1412
+ if (!fs3.existsSync(manifestPath)) {
1362
1413
  jsonResponse(res, 404, { error: "Manifest not found" });
1363
1414
  return;
1364
1415
  }
1365
- const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
1416
+ const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
1366
1417
  const themeName = sanitizeFileName(manifest.theme || "default");
1367
1418
  const themePath = themesResource.filePath(themeName);
1368
- if (!fs2.existsSync(themePath)) {
1419
+ if (!fs3.existsSync(themePath)) {
1369
1420
  jsonResponse(res, 422, { error: `Manifest references missing theme: ${themeName}` });
1370
1421
  return;
1371
1422
  }
1372
- const theme = JSON.parse(fs2.readFileSync(themePath, "utf-8"));
1423
+ const theme = JSON.parse(fs3.readFileSync(themePath, "utf-8"));
1373
1424
  const knownComponents = new Set(listComponentNames());
1374
1425
  const componentConfigs = {};
1375
1426
  for (const [comp, configFile] of Object.entries(manifest.componentConfigs ?? {})) {
@@ -1377,13 +1428,13 @@ function themeFileApi(opts) {
1377
1428
  const sanitized = sanitizeFileName(String(configFile) || "default");
1378
1429
  if (sanitized === "default") continue;
1379
1430
  const cfgPath = componentResource(comp).filePath(sanitized);
1380
- if (!fs2.existsSync(cfgPath)) {
1431
+ if (!fs3.existsSync(cfgPath)) {
1381
1432
  jsonResponse(res, 422, {
1382
1433
  error: `Manifest references missing config: ${comp}/${sanitized}`
1383
1434
  });
1384
1435
  return;
1385
1436
  }
1386
- const cfg = JSON.parse(fs2.readFileSync(cfgPath, "utf-8"));
1437
+ const cfg = JSON.parse(fs3.readFileSync(cfgPath, "utf-8"));
1387
1438
  componentConfigs[`${comp}/${sanitized}`] = cfg;
1388
1439
  }
1389
1440
  const bundle = {
@@ -1405,7 +1456,7 @@ function themeFileApi(opts) {
1405
1456
  }
1406
1457
  function nextAvailableName2(resourceFilePath, baseName) {
1407
1458
  return nextAvailableName(
1408
- (n) => fs2.existsSync(resourceFilePath(n)),
1459
+ (n) => fs3.existsSync(resourceFilePath(n)),
1409
1460
  sanitizeFileName(baseName)
1410
1461
  );
1411
1462
  }
@@ -1447,7 +1498,7 @@ function themeFileApi(opts) {
1447
1498
  themeBody.updatedAt = now;
1448
1499
  if (!themeBody.createdAt) themeBody.createdAt = now;
1449
1500
  themesResource.ensureDir();
1450
- fs2.writeFileSync(themesResource.filePath(finalThemeName), JSON.stringify(themeBody, null, 2));
1501
+ fs3.writeFileSync(themesResource.filePath(finalThemeName), JSON.stringify(themeBody, null, 2));
1451
1502
  const knownComponents = new Set(listComponentNames());
1452
1503
  const componentRenames = {};
1453
1504
  for (const [key, cfgValue] of Object.entries(bundle.componentConfigs)) {
@@ -1469,7 +1520,7 @@ function themeFileApi(opts) {
1469
1520
  cfgBody.updatedAt = now;
1470
1521
  if (!cfgBody.createdAt) cfgBody.createdAt = now;
1471
1522
  r.ensureDir();
1472
- fs2.writeFileSync(r.filePath(finalName), JSON.stringify(cfgBody, null, 2));
1523
+ fs3.writeFileSync(r.filePath(finalName), JSON.stringify(cfgBody, null, 2));
1473
1524
  }
1474
1525
  const rewrittenManifest = {
1475
1526
  ...bundle.manifest,
@@ -1496,7 +1547,7 @@ function themeFileApi(opts) {
1496
1547
  renames[`manifest:${originalManifestName}`] = finalManifestName;
1497
1548
  }
1498
1549
  manifestsResource.ensureDir();
1499
- fs2.writeFileSync(
1550
+ fs3.writeFileSync(
1500
1551
  manifestsResource.filePath(finalManifestName),
1501
1552
  JSON.stringify(rewrittenManifest, null, 2)
1502
1553
  );
@@ -1569,7 +1620,8 @@ function themeFileApi(opts) {
1569
1620
  return {
1570
1621
  define: {
1571
1622
  __PROJECT_ROOT__: JSON.stringify(process.cwd()),
1572
- __APP_VERSION__: JSON.stringify(PKG_VERSION)
1623
+ __APP_VERSION__: JSON.stringify(PKG_VERSION),
1624
+ __LIVE_TOKENS_API_BASE__: JSON.stringify(API_BASE)
1573
1625
  }
1574
1626
  };
1575
1627
  },
@@ -1584,7 +1636,7 @@ function themeFileApi(opts) {
1584
1636
  });
1585
1637
  },
1586
1638
  handleHotUpdate(ctx) {
1587
- const normalized = path2.resolve(ctx.file);
1639
+ const normalized = path3.resolve(ctx.file);
1588
1640
  if (!normalized.startsWith(COMPONENTS_SRC_DIR)) return;
1589
1641
  if (!normalized.endsWith(".svelte")) return;
1590
1642
  const comp = componentNameFromFile(normalized);