canvas-ui-sdk 0.3.0 → 0.3.1

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/dist/index.d.ts CHANGED
@@ -4754,12 +4754,21 @@ interface ThemeDrawerProps {
4754
4754
  onBrandingChange?: (branding: BrandingState) => void;
4755
4755
  onImagesChange?: (images: Record<ImageKey, string>) => void;
4756
4756
  onImageUpload?: (key: ImageKey, file: File) => Promise<string>;
4757
+ onSave?: (themeData: {
4758
+ overrides: Record<string, string>;
4759
+ branding: BrandingState;
4760
+ images: Record<ImageKey, string>;
4761
+ customButtonStyles: CustomButtonStyle[];
4762
+ }) => void;
4757
4763
  initialOverrides?: Record<string, string>;
4764
+ initialBranding?: BrandingState;
4765
+ initialImages?: Record<ImageKey, string>;
4766
+ initialCustomButtonStyles?: CustomButtonStyle[];
4758
4767
  storageKey?: string;
4759
4768
  title?: string;
4760
4769
  width?: number;
4761
4770
  }
4762
- declare function ThemeDrawer({ devOnly, triggerPosition, defaultOpen, panels: enabledPanels, onThemeChange, onBrandingChange, onImagesChange, onImageUpload, initialOverrides, storageKey, title, width, }: ThemeDrawerProps): react_jsx_runtime.JSX.Element | null;
4771
+ declare function ThemeDrawer({ devOnly, triggerPosition, defaultOpen, panels: enabledPanels, onThemeChange, onBrandingChange, onImagesChange, onImageUpload, onSave, initialOverrides, initialBranding, initialImages, initialCustomButtonStyles, storageKey, title, width, }: ThemeDrawerProps): react_jsx_runtime.JSX.Element | null;
4763
4772
 
4764
4773
  interface HslColorPickerProps {
4765
4774
  value: string;
package/dist/index.js CHANGED
@@ -165,7 +165,8 @@ var sizeStyles = {
165
165
  fontSize: "var(--btn-mini-font-size)",
166
166
  borderRadius: "var(--btn-mini-radius)",
167
167
  fontWeight: "var(--btn-mini-font-weight)",
168
- letterSpacing: "var(--btn-mini-letter-spacing)"
168
+ letterSpacing: "var(--btn-mini-letter-spacing)",
169
+ fontFamily: "var(--btn-mini-font-family, var(--typo-button-font, var(--typo-global-font)))"
169
170
  },
170
171
  sm: {
171
172
  height: "var(--btn-small-height)",
@@ -174,7 +175,8 @@ var sizeStyles = {
174
175
  fontSize: "var(--btn-small-font-size)",
175
176
  borderRadius: "var(--btn-small-radius)",
176
177
  fontWeight: "var(--btn-small-font-weight)",
177
- letterSpacing: "var(--btn-small-letter-spacing)"
178
+ letterSpacing: "var(--btn-small-letter-spacing)",
179
+ fontFamily: "var(--btn-small-font-family, var(--typo-button-font, var(--typo-global-font)))"
178
180
  },
179
181
  default: {
180
182
  height: "var(--btn-standard-height)",
@@ -183,7 +185,8 @@ var sizeStyles = {
183
185
  fontSize: "var(--btn-standard-font-size)",
184
186
  borderRadius: "var(--btn-standard-radius)",
185
187
  fontWeight: "var(--btn-standard-font-weight)",
186
- letterSpacing: "var(--btn-standard-letter-spacing)"
188
+ letterSpacing: "var(--btn-standard-letter-spacing)",
189
+ fontFamily: "var(--btn-standard-font-family, var(--typo-button-font, var(--typo-global-font)))"
187
190
  },
188
191
  lg: {
189
192
  height: "var(--btn-large-height)",
@@ -192,7 +195,8 @@ var sizeStyles = {
192
195
  fontSize: "var(--btn-large-font-size)",
193
196
  borderRadius: "var(--btn-large-radius)",
194
197
  fontWeight: "var(--btn-large-font-weight)",
195
- letterSpacing: "var(--btn-large-letter-spacing)"
198
+ letterSpacing: "var(--btn-large-letter-spacing)",
199
+ fontFamily: "var(--btn-large-font-family, var(--typo-button-font, var(--typo-global-font)))"
196
200
  }
197
201
  };
198
202
  var canvasVariants = ["primary", "primary-outline", "primary-neutral", "neutral", "neutral-delete", "delete"];
@@ -4560,19 +4564,24 @@ function Sidebar2({
4560
4564
  }
4561
4565
 
4562
4566
  // src/lib/css-variable-sync.ts
4567
+ function getStyleTarget() {
4568
+ return document.body ?? document.documentElement;
4569
+ }
4563
4570
  function setCSSVariable(name, value) {
4564
- document.documentElement.style.setProperty(name, value);
4571
+ getStyleTarget().style.setProperty(name, value);
4565
4572
  broadcastCSSVariables({ [name]: value });
4566
4573
  }
4567
4574
  function setCSSVariables(variables) {
4575
+ const target = getStyleTarget();
4568
4576
  Object.entries(variables).forEach(([name, value]) => {
4569
- document.documentElement.style.setProperty(name, value);
4577
+ target.style.setProperty(name, value);
4570
4578
  });
4571
4579
  broadcastCSSVariables(variables);
4572
4580
  }
4573
4581
  function removeCSSVariables(names) {
4582
+ const target = getStyleTarget();
4574
4583
  names.forEach((name) => {
4575
- document.documentElement.style.removeProperty(name);
4584
+ target.style.removeProperty(name);
4576
4585
  });
4577
4586
  const iframes = document.querySelectorAll("iframe");
4578
4587
  iframes.forEach((iframe) => {
@@ -24230,6 +24239,86 @@ function isVariableReference(value) {
24230
24239
  return value?.startsWith("var(") ?? false;
24231
24240
  }
24232
24241
 
24242
+ // src/components/theme-drawer/components/font-config.ts
24243
+ var googleFontFamilies = {
24244
+ // Sans-Serif
24245
+ Inter: "Inter",
24246
+ Geist: "Geist",
24247
+ "Plus Jakarta Sans": "Plus+Jakarta+Sans",
24248
+ Poppins: "Poppins",
24249
+ "IBM Plex Sans": "IBM+Plex+Sans",
24250
+ Roboto: "Roboto",
24251
+ "Open Sans": "Open+Sans",
24252
+ "Noto Sans": "Noto+Sans",
24253
+ Montserrat: "Montserrat",
24254
+ Lato: "Lato",
24255
+ Raleway: "Raleway",
24256
+ "DM Sans": "DM+Sans",
24257
+ "Work Sans": "Work+Sans",
24258
+ Manrope: "Manrope",
24259
+ Outfit: "Outfit",
24260
+ "Source Sans 3": "Source+Sans+3",
24261
+ // Serif
24262
+ "Playfair Display": "Playfair+Display",
24263
+ Merriweather: "Merriweather",
24264
+ "Noto Serif": "Noto+Serif",
24265
+ "Libre Baskerville": "Libre+Baskerville",
24266
+ // Monospace
24267
+ "IBM Plex Mono": "IBM+Plex+Mono",
24268
+ "Courier Prime": "Courier+Prime",
24269
+ "Geist Mono": "Geist+Mono"
24270
+ };
24271
+ var loadedFonts = /* @__PURE__ */ new Set();
24272
+ function loadGoogleFont(fontName) {
24273
+ if (loadedFonts.has(fontName)) return;
24274
+ const fontFamily = googleFontFamilies[fontName];
24275
+ if (!fontFamily) return;
24276
+ const link = document.createElement("link");
24277
+ link.rel = "stylesheet";
24278
+ link.href = `https://fonts.googleapis.com/css2?family=${fontFamily}:wght@400;500;600;700&display=swap`;
24279
+ document.head.appendChild(link);
24280
+ loadedFonts.add(fontName);
24281
+ }
24282
+ var fontsPreloaded = false;
24283
+ function preloadAllFonts() {
24284
+ if (fontsPreloaded) return;
24285
+ Object.keys(googleFontFamilies).forEach((fontName) => {
24286
+ loadGoogleFont(fontName);
24287
+ });
24288
+ fontsPreloaded = true;
24289
+ }
24290
+ var fontOptions = [
24291
+ { value: "Courier Prime", label: "Courier Prime" },
24292
+ { value: "DM Sans", label: "DM Sans" },
24293
+ { value: "Geist", label: "Geist" },
24294
+ { value: "Geist Mono", label: "Geist Mono" },
24295
+ { value: "IBM Plex Mono", label: "IBM Plex Mono" },
24296
+ { value: "IBM Plex Sans", label: "IBM Plex Sans" },
24297
+ { value: "Inter", label: "Inter" },
24298
+ { value: "Lato", label: "Lato" },
24299
+ { value: "Libre Baskerville", label: "Libre Baskerville" },
24300
+ { value: "Manrope", label: "Manrope" },
24301
+ { value: "Merriweather", label: "Merriweather" },
24302
+ { value: "Montserrat", label: "Montserrat" },
24303
+ { value: "Noto Sans", label: "Noto Sans" },
24304
+ { value: "Noto Serif", label: "Noto Serif" },
24305
+ { value: "Open Sans", label: "Open Sans" },
24306
+ { value: "Outfit", label: "Outfit" },
24307
+ { value: "Playfair Display", label: "Playfair Display" },
24308
+ { value: "Plus Jakarta Sans", label: "Plus Jakarta Sans" },
24309
+ { value: "Poppins", label: "Poppins" },
24310
+ { value: "Raleway", label: "Raleway" },
24311
+ { value: "Roboto", label: "Roboto" },
24312
+ { value: "Source Sans 3", label: "Source Sans 3" },
24313
+ { value: "Work Sans", label: "Work Sans" }
24314
+ ];
24315
+ var fontWeightOptions = [
24316
+ { value: "400", label: "Regular (400)" },
24317
+ { value: "500", label: "Medium (500)" },
24318
+ { value: "600", label: "Semibold (600)" },
24319
+ { value: "700", label: "Bold (700)" }
24320
+ ];
24321
+
24233
24322
  // src/components/theme-drawer/hooks/use-theme-state.ts
24234
24323
  var FONT_VARS = [
24235
24324
  "--typo-h1-font",
@@ -24293,30 +24382,54 @@ function isEqual(a, b) {
24293
24382
  }
24294
24383
  return false;
24295
24384
  }
24385
+ var FONT_VAR_PREFIXES = ["--typo-", "--btn-"];
24386
+ var FONT_VAR_SUFFIXES = ["-font", "-font-family"];
24387
+ function loadFontsFromOverrides(overrides) {
24388
+ for (const [key, value] of Object.entries(overrides)) {
24389
+ if (!value) continue;
24390
+ const isFontVar = FONT_VAR_PREFIXES.some((p) => key.startsWith(p)) && FONT_VAR_SUFFIXES.some((s) => key.endsWith(s));
24391
+ if (isFontVar) {
24392
+ const fontName = value.replace(/^["']|["']$/g, "").split(",")[0].trim();
24393
+ if (fontName) loadGoogleFont(fontName);
24394
+ }
24395
+ }
24396
+ }
24296
24397
  function useThemeState(options) {
24297
24398
  const {
24298
24399
  storageKey = "canvas-ui-theme",
24299
24400
  initialOverrides,
24401
+ initialBranding,
24402
+ initialImages,
24403
+ initialCustomButtonStyles,
24300
24404
  onThemeChange,
24301
24405
  onBrandingChange,
24302
- onImagesChange
24406
+ onImagesChange,
24407
+ onSave
24303
24408
  } = options ?? {};
24304
24409
  const [savedOverrides, setSavedOverrides] = useState(() => {
24305
24410
  return initialOverrides ?? {};
24306
24411
  });
24307
- const [savedBranding, setSavedBranding] = useState({ ...defaultBranding });
24308
- const [savedImages, setSavedImages] = useState({ ...defaultImages });
24309
- const [savedCustomButtonStyles, setSavedCustomButtonStyles] = useState([
24310
- ...defaultCustomButtonStyles
24311
- ]);
24412
+ const [savedBranding, setSavedBranding] = useState(
24413
+ () => initialBranding ?? { ...defaultBranding }
24414
+ );
24415
+ const [savedImages, setSavedImages] = useState(
24416
+ () => initialImages ?? { ...defaultImages }
24417
+ );
24418
+ const [savedCustomButtonStyles, setSavedCustomButtonStyles] = useState(
24419
+ () => initialCustomButtonStyles ?? [...defaultCustomButtonStyles]
24420
+ );
24312
24421
  const [overrides, setOverrides] = useState(() => {
24313
24422
  return initialOverrides ?? {};
24314
24423
  });
24315
- const [branding, setBrandingState] = useState({ ...defaultBranding });
24316
- const [images, setImagesState] = useState({ ...defaultImages });
24317
- const [customButtonStyles, setCustomButtonStyles] = useState([
24318
- ...defaultCustomButtonStyles
24319
- ]);
24424
+ const [branding, setBrandingState] = useState(
24425
+ () => initialBranding ?? { ...defaultBranding }
24426
+ );
24427
+ const [images, setImagesState] = useState(
24428
+ () => initialImages ?? { ...defaultImages }
24429
+ );
24430
+ const [customButtonStyles, setCustomButtonStyles] = useState(
24431
+ () => initialCustomButtonStyles ?? [...defaultCustomButtonStyles]
24432
+ );
24320
24433
  const [brandHue, setBrandHueState] = useState(217);
24321
24434
  const [brandVibrancy, setBrandVibrancyState] = useState(1);
24322
24435
  const [syncRelatedColors, setSyncRelatedColorsState] = useState(true);
@@ -24326,6 +24439,8 @@ function useThemeState(options) {
24326
24439
  onBrandingChangeRef.current = onBrandingChange;
24327
24440
  const onImagesChangeRef = useRef(onImagesChange);
24328
24441
  onImagesChangeRef.current = onImagesChange;
24442
+ const onSaveRef = useRef(onSave);
24443
+ onSaveRef.current = onSave;
24329
24444
  const persistToStorage = useCallback(
24330
24445
  (ovr, brd, img, cbs) => {
24331
24446
  try {
@@ -24340,6 +24455,11 @@ function useThemeState(options) {
24340
24455
  );
24341
24456
  useEffect(() => {
24342
24457
  try {
24458
+ if (initialOverrides && Object.keys(initialOverrides).length > 0) {
24459
+ setCSSVariables(initialOverrides);
24460
+ loadFontsFromOverrides(initialOverrides);
24461
+ return;
24462
+ }
24343
24463
  const stored = localStorage.getItem(storageKey);
24344
24464
  if (stored) {
24345
24465
  const parsed = importJSON(stored);
@@ -24348,6 +24468,7 @@ function useThemeState(options) {
24348
24468
  setSavedOverrides(parsed.overrides);
24349
24469
  setOverrides(parsed.overrides);
24350
24470
  setCSSVariables(parsed.overrides);
24471
+ loadFontsFromOverrides(parsed.overrides);
24351
24472
  }
24352
24473
  if (parsed.branding) {
24353
24474
  setSavedBranding(parsed.branding);
@@ -24366,8 +24487,6 @@ function useThemeState(options) {
24366
24487
  setBrandHueState(hsl.h);
24367
24488
  }
24368
24489
  }
24369
- } else if (initialOverrides) {
24370
- setCSSVariables(initialOverrides);
24371
24490
  }
24372
24491
  } catch {
24373
24492
  }
@@ -24420,6 +24539,12 @@ function useThemeState(options) {
24420
24539
  setSavedImages(currentImages);
24421
24540
  setSavedCustomButtonStyles(currentCbs);
24422
24541
  persistToStorage(currentOverrides, currentBranding, currentImages, currentCbs);
24542
+ onSaveRef.current?.({
24543
+ overrides: currentOverrides,
24544
+ branding: currentBranding,
24545
+ images: currentImages,
24546
+ customButtonStyles: currentCbs
24547
+ });
24423
24548
  return currentCbs;
24424
24549
  });
24425
24550
  return currentImages;
@@ -24564,7 +24689,7 @@ function useThemeState(options) {
24564
24689
  const defaultHsl = hexToHsl2(defaultColor);
24565
24690
  const newHex = hslToHex2(hue, defaultHsl.s, defaultHsl.l);
24566
24691
  newValues["--canvas-primary"] = newHex;
24567
- document.documentElement.style.setProperty("--canvas-primary", newHex);
24692
+ (document.body ?? document.documentElement).style.setProperty("--canvas-primary", newHex);
24568
24693
  }
24569
24694
  }
24570
24695
  setOverrides((prev) => {
@@ -24572,7 +24697,7 @@ function useThemeState(options) {
24572
24697
  varsToUpdate.forEach((varName) => {
24573
24698
  if (varName === "--canvas-sidebar-light-active-text" || varName === "--canvas-border-input-focus") {
24574
24699
  newValues[varName] = effectivePrimaryColor;
24575
- document.documentElement.style.setProperty(varName, effectivePrimaryColor);
24700
+ (document.body ?? document.documentElement).style.setProperty(varName, effectivePrimaryColor);
24576
24701
  return;
24577
24702
  }
24578
24703
  if (varName === "--canvas-primary") return;
@@ -24592,7 +24717,7 @@ function useThemeState(options) {
24592
24717
  );
24593
24718
  const newHex = hslToHex2(hue, newS, newL);
24594
24719
  newValues[varName] = newHex;
24595
- document.documentElement.style.setProperty(varName, newHex);
24720
+ (document.body ?? document.documentElement).style.setProperty(varName, newHex);
24596
24721
  });
24597
24722
  const next = { ...prev, ...newValues };
24598
24723
  onThemeChangeRef.current?.(next);
@@ -25805,86 +25930,6 @@ function ImageUploadRow({
25805
25930
  }
25806
25931
  );
25807
25932
  }
25808
-
25809
- // src/components/theme-drawer/components/font-config.ts
25810
- var googleFontFamilies = {
25811
- // Sans-Serif
25812
- Inter: "Inter",
25813
- Geist: "Geist",
25814
- "Plus Jakarta Sans": "Plus+Jakarta+Sans",
25815
- Poppins: "Poppins",
25816
- "IBM Plex Sans": "IBM+Plex+Sans",
25817
- Roboto: "Roboto",
25818
- "Open Sans": "Open+Sans",
25819
- "Noto Sans": "Noto+Sans",
25820
- Montserrat: "Montserrat",
25821
- Lato: "Lato",
25822
- Raleway: "Raleway",
25823
- "DM Sans": "DM+Sans",
25824
- "Work Sans": "Work+Sans",
25825
- Manrope: "Manrope",
25826
- Outfit: "Outfit",
25827
- "Source Sans 3": "Source+Sans+3",
25828
- // Serif
25829
- "Playfair Display": "Playfair+Display",
25830
- Merriweather: "Merriweather",
25831
- "Noto Serif": "Noto+Serif",
25832
- "Libre Baskerville": "Libre+Baskerville",
25833
- // Monospace
25834
- "IBM Plex Mono": "IBM+Plex+Mono",
25835
- "Courier Prime": "Courier+Prime",
25836
- "Geist Mono": "Geist+Mono"
25837
- };
25838
- var loadedFonts = /* @__PURE__ */ new Set();
25839
- function loadGoogleFont(fontName) {
25840
- if (loadedFonts.has(fontName)) return;
25841
- const fontFamily = googleFontFamilies[fontName];
25842
- if (!fontFamily) return;
25843
- const link = document.createElement("link");
25844
- link.rel = "stylesheet";
25845
- link.href = `https://fonts.googleapis.com/css2?family=${fontFamily}:wght@400;500;600;700&display=swap`;
25846
- document.head.appendChild(link);
25847
- loadedFonts.add(fontName);
25848
- }
25849
- var fontsPreloaded = false;
25850
- function preloadAllFonts() {
25851
- if (fontsPreloaded) return;
25852
- Object.keys(googleFontFamilies).forEach((fontName) => {
25853
- loadGoogleFont(fontName);
25854
- });
25855
- fontsPreloaded = true;
25856
- }
25857
- var fontOptions = [
25858
- { value: "Courier Prime", label: "Courier Prime" },
25859
- { value: "DM Sans", label: "DM Sans" },
25860
- { value: "Geist", label: "Geist" },
25861
- { value: "Geist Mono", label: "Geist Mono" },
25862
- { value: "IBM Plex Mono", label: "IBM Plex Mono" },
25863
- { value: "IBM Plex Sans", label: "IBM Plex Sans" },
25864
- { value: "Inter", label: "Inter" },
25865
- { value: "Lato", label: "Lato" },
25866
- { value: "Libre Baskerville", label: "Libre Baskerville" },
25867
- { value: "Manrope", label: "Manrope" },
25868
- { value: "Merriweather", label: "Merriweather" },
25869
- { value: "Montserrat", label: "Montserrat" },
25870
- { value: "Noto Sans", label: "Noto Sans" },
25871
- { value: "Noto Serif", label: "Noto Serif" },
25872
- { value: "Open Sans", label: "Open Sans" },
25873
- { value: "Outfit", label: "Outfit" },
25874
- { value: "Playfair Display", label: "Playfair Display" },
25875
- { value: "Plus Jakarta Sans", label: "Plus Jakarta Sans" },
25876
- { value: "Poppins", label: "Poppins" },
25877
- { value: "Raleway", label: "Raleway" },
25878
- { value: "Roboto", label: "Roboto" },
25879
- { value: "Source Sans 3", label: "Source Sans 3" },
25880
- { value: "Work Sans", label: "Work Sans" }
25881
- ];
25882
- var fontWeightOptions = [
25883
- { value: "400", label: "Regular (400)" },
25884
- { value: "500", label: "Medium (500)" },
25885
- { value: "600", label: "Semibold (600)" },
25886
- { value: "700", label: "Bold (700)" }
25887
- ];
25888
25933
  var typographyColorOptions = [
25889
25934
  { value: "var(--canvas-text)", label: "Text" },
25890
25935
  { value: "var(--canvas-text-muted)", label: "Text Muted" },
@@ -27550,7 +27595,11 @@ function ThemeDrawer({
27550
27595
  onBrandingChange,
27551
27596
  onImagesChange,
27552
27597
  onImageUpload,
27598
+ onSave,
27553
27599
  initialOverrides,
27600
+ initialBranding,
27601
+ initialImages,
27602
+ initialCustomButtonStyles,
27554
27603
  storageKey,
27555
27604
  title = "Design Variables",
27556
27605
  width = 464
@@ -27564,9 +27613,13 @@ function ThemeDrawer({
27564
27613
  const theme = useThemeState({
27565
27614
  storageKey,
27566
27615
  initialOverrides,
27616
+ initialBranding,
27617
+ initialImages,
27618
+ initialCustomButtonStyles,
27567
27619
  onThemeChange,
27568
27620
  onBrandingChange,
27569
- onImagesChange
27621
+ onImagesChange,
27622
+ onSave
27570
27623
  });
27571
27624
  const { setPreviewBranding, setPreviewImages } = usePreviewBranding();
27572
27625
  useEffect(() => {