funuicss 3.7.15 → 3.7.16

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/ui/theme/theme.js CHANGED
@@ -280,7 +280,7 @@ exports.getAllVariables = getAllVariables;
280
280
  /* COMPONENT */
281
281
  /* -------------------------------------------------------------------------- */
282
282
  var ThemeProvider = function (_a) {
283
- var theme = _a.theme, children = _a.children, _b = _a.funcss, funcss = _b === void 0 ? '' : _b, _c = _a.minHeight, minHeight = _c === void 0 ? '100vh' : _c, projectId = _a.projectId;
283
+ var theme = _a.theme, children = _a.children, _b = _a.funcss, funcss = _b === void 0 ? '' : _b, _c = _a.minHeight, minHeight = _c === void 0 ? '100vh' : _c, projectId = _a.projectId, providedProject = _a.project;
284
284
  var _d = (0, react_1.useState)('standard'), variant = _d[0], setVariant = _d[1];
285
285
  var _e = (0, react_1.useState)({}), themeConfig = _e[0], setThemeConfig = _e[1];
286
286
  var _f = (0, react_1.useState)(null), projectData = _f[0], setProjectData = _f[1];
@@ -323,20 +323,25 @@ var ThemeProvider = function (_a) {
323
323
  return __generator(this, function (_a) {
324
324
  switch (_a.label) {
325
325
  case 0:
326
- _a.trys.push([0, 8, 9, 10]);
326
+ _a.trys.push([0, 9, 10, 11]);
327
327
  finalTheme = null;
328
328
  finalVersion = null;
329
- return [4 /*yield*/, loadLocalTheme()];
330
- case 1:
329
+ if (!providedProject) return [3 /*break*/, 1];
330
+ console.log('✅ Using provided project data directly');
331
+ finalTheme = providedProject;
332
+ finalVersion = providedProject.version || 0;
333
+ return [3 /*break*/, 8];
334
+ case 1: return [4 /*yield*/, loadLocalTheme()];
335
+ case 2:
331
336
  localTheme = _a.sent();
332
337
  localVersion = (localTheme === null || localTheme === void 0 ? void 0 : localTheme.version) || 0;
333
- if (!projectId) return [3 /*break*/, 6];
338
+ if (!projectId) return [3 /*break*/, 7];
334
339
  return [4 /*yield*/, validateOriginAccess(projectId)];
335
- case 2:
340
+ case 3:
336
341
  hasAccess = _a.sent();
337
- if (!hasAccess) return [3 /*break*/, 4];
342
+ if (!hasAccess) return [3 /*break*/, 5];
338
343
  return [4 /*yield*/, loadThemeFromCDN(projectId)];
339
- case 3:
344
+ case 4:
340
345
  cdnTheme = _a.sent();
341
346
  cdnVersion = (cdnTheme === null || cdnTheme === void 0 ? void 0 : cdnTheme.version) || 0;
342
347
  if (cdnTheme) {
@@ -359,8 +364,8 @@ var ThemeProvider = function (_a) {
359
364
  console.warn('⚠️ No theme found (CDN unavailable and no local theme)');
360
365
  setError('Theme not found');
361
366
  }
362
- return [3 /*break*/, 5];
363
- case 4:
367
+ return [3 /*break*/, 6];
368
+ case 5:
364
369
  // Origin validation failed
365
370
  if (localTheme) {
366
371
  console.log('⚠️ Origin validation failed, using local theme');
@@ -371,9 +376,9 @@ var ThemeProvider = function (_a) {
371
376
  console.error('❌ Origin validation failed and no local theme available');
372
377
  setError('Access denied and no local theme available');
373
378
  }
374
- _a.label = 5;
375
- case 5: return [3 /*break*/, 7];
376
- case 6:
379
+ _a.label = 6;
380
+ case 6: return [3 /*break*/, 8];
381
+ case 7:
377
382
  // No project ID provided - only use local theme
378
383
  console.log('ℹ️ No project ID provided, using local theme only');
379
384
  if (localTheme) {
@@ -385,8 +390,8 @@ var ThemeProvider = function (_a) {
385
390
  console.log('ℹ️ No local theme file found - using base theme only');
386
391
  // No error here - it's valid to use only base theme
387
392
  }
388
- _a.label = 7;
389
- case 7:
393
+ _a.label = 8;
394
+ case 8:
390
395
  // Apply the theme if we have one
391
396
  if (finalTheme && (!currentVersion || finalVersion !== currentVersion)) {
392
397
  applyThemeData(finalTheme, root);
@@ -396,24 +401,24 @@ var ThemeProvider = function (_a) {
396
401
  else if (finalTheme) {
397
402
  console.log('✓ Theme up to date');
398
403
  }
399
- return [3 /*break*/, 10];
400
- case 8:
404
+ return [3 /*break*/, 11];
405
+ case 9:
401
406
  err_1 = _a.sent();
402
407
  console.error('❌ Error loading theme:', err_1);
403
408
  setError('Failed to load theme');
404
- return [3 /*break*/, 10];
405
- case 9:
409
+ return [3 /*break*/, 11];
410
+ case 10:
406
411
  setIsLoading(false);
407
412
  setIsInitialLoad(false);
408
413
  return [7 /*endfinally*/];
409
- case 10: return [2 /*return*/];
414
+ case 11: return [2 /*return*/];
410
415
  }
411
416
  });
412
417
  }); };
413
418
  // Initial load
414
419
  loadTheme();
415
- // Only poll for updates if we have a project ID
416
- if (projectId) {
420
+ // Only poll for updates if we have a project ID AND no provided project
421
+ if (projectId && !providedProject) {
417
422
  pollTimer = setInterval(function () {
418
423
  loadTheme();
419
424
  }, 5 * 60 * 1000);
@@ -423,7 +428,7 @@ var ThemeProvider = function (_a) {
423
428
  clearInterval(pollTimer);
424
429
  }
425
430
  };
426
- }, [projectId, currentVersion, theme]);
431
+ }, [projectId, currentVersion, theme, providedProject]); // Added providedProject to dependencies
427
432
  var applyThemeData = function (data, root) {
428
433
  var _a;
429
434
  var themeConfig = (_a = data.theme_config) !== null && _a !== void 0 ? _a : {};
@@ -619,3 +624,546 @@ var useDocumentAssets = function () {
619
624
  return (0, exports.useAssetsByType)('document');
620
625
  };
621
626
  exports.useDocumentAssets = useDocumentAssets;
627
+ // 'use client'
628
+ // import React, {
629
+ // useEffect,
630
+ // createContext,
631
+ // useContext,
632
+ // useState,
633
+ // ReactNode,
634
+ // useMemo,
635
+ // } from 'react'
636
+ // import { colorVarsToDarken, themes } from './themes'
637
+ // import { getDarkenAmount, darkenToRgba } from './darkenUtils'
638
+ // /* -------------------------------------------------------------------------- */
639
+ // /* TYPES */
640
+ // /* -------------------------------------------------------------------------- */
641
+ // export type ThemeVariant = 'standard' | 'minimal'
642
+ // export type ThemeName =
643
+ // | 'light'
644
+ // | 'dark'
645
+ // | 'dark-blue'
646
+ // | 'light-gray'
647
+ // | 'pastel-green'
648
+ // | 'warm-orange'
649
+ // | 'frosted-glass'
650
+ // | 'midnight-purple'
651
+ // | 'cyber-metal'
652
+ // interface ThemeConfig {
653
+ // [key: string]: any
654
+ // }
655
+ // interface Variable {
656
+ // name: string
657
+ // value: any
658
+ // }
659
+ // interface ProjectData {
660
+ // theme_config?: {
661
+ // colors?: Record<string, string>
662
+ // typography?: Record<string, string>
663
+ // [key: string]: any
664
+ // }
665
+ // components?: Record<string, any>
666
+ // default_variation?: ThemeVariant
667
+ // variables?: Variable[]
668
+ // assets?: Asset[]
669
+ // name?: string
670
+ // project_id?: string
671
+ // version?: number
672
+ // updated_at?: string
673
+ // trustedDomains?: Array<{
674
+ // domain: string
675
+ // status: string
676
+ // isDefault?: boolean
677
+ // }>
678
+ // }
679
+ // interface ThemeProviderProps {
680
+ // theme: ThemeName
681
+ // projectId?: string
682
+ // funcss?: string
683
+ // minHeight?: string
684
+ // children: ReactNode
685
+ // }
686
+ // /* -------------------------------------------------------------------------- */
687
+ // /* THEME CONTEXT */
688
+ // /* -------------------------------------------------------------------------- */
689
+ // interface ThemeContextType {
690
+ // variant: ThemeVariant
691
+ // setVariant: React.Dispatch<React.SetStateAction<ThemeVariant>>
692
+ // themeConfig: ThemeConfig
693
+ // projectData: ProjectData | null
694
+ // isLoading: boolean
695
+ // isInitialLoad: boolean
696
+ // error: string | null
697
+ // }
698
+ // const ThemeContext = createContext<ThemeContextType>({
699
+ // variant: 'standard',
700
+ // setVariant: () => {},
701
+ // themeConfig: {},
702
+ // projectData: null,
703
+ // isLoading: true,
704
+ // isInitialLoad: true,
705
+ // error: null,
706
+ // })
707
+ // export const useTheme = (): ThemeContextType => {
708
+ // const context = useContext(ThemeContext)
709
+ // if (!context) {
710
+ // throw new Error('useTheme must be used within ThemeProvider')
711
+ // }
712
+ // return context
713
+ // }
714
+ // export const useVariant = () => {
715
+ // const { variant, setVariant } = useTheme()
716
+ // return { variant, setVariant }
717
+ // }
718
+ // /* -------------------------------------------------------------------------- */
719
+ // /* ORIGIN VALIDATION */
720
+ // /* -------------------------------------------------------------------------- */
721
+ // const getCurrentOrigin = (): string => {
722
+ // if (typeof window === 'undefined') return ''
723
+ // // For local development, return localhost
724
+ // if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') {
725
+ // return 'localhost'
726
+ // }
727
+ // // For production, return the domain without protocol and www
728
+ // let domain = window.location.hostname
729
+ // domain = domain.replace(/^www\./, '')
730
+ // return domain
731
+ // }
732
+ // const validateOriginAccess = async (projectId: string): Promise<boolean> => {
733
+ // if (!projectId) {
734
+ // console.error('❌ No project ID provided for origin validation')
735
+ // return false
736
+ // }
737
+ // const currentOrigin = getCurrentOrigin()
738
+ // console.log(`🔍 Validating origin access for: ${currentOrigin}`)
739
+ // try {
740
+ // // Load project data from CDN to check trusted domains
741
+ // const projectData = await loadThemeFromCDN(projectId)
742
+ // if (!projectData) {
743
+ // console.error('❌ Project not found or inaccessible')
744
+ // return false
745
+ // }
746
+ // const trustedDomains = projectData.trustedDomains || []
747
+ // // Check if current origin is in trusted domains
748
+ // const hasAccess = trustedDomains.some(domain => {
749
+ // const trustedDomain = domain.domain.toLowerCase()
750
+ // const currentDomain = currentOrigin.toLowerCase()
751
+ // // Exact match or subdomain match
752
+ // return currentDomain === trustedDomain ||
753
+ // currentDomain.endsWith('.' + trustedDomain) ||
754
+ // (trustedDomain === 'localhost' && currentOrigin === 'localhost')
755
+ // })
756
+ // if (!hasAccess) {
757
+ // console.error(`❌ Access denied: Origin "${currentOrigin}" is not in trusted domains`)
758
+ // console.log('📋 Trusted domains:', trustedDomains.map(d => d.domain))
759
+ // return false
760
+ // }
761
+ // return true
762
+ // } catch (error) {
763
+ // console.error('❌ Error during origin validation:', error)
764
+ // return false
765
+ // }
766
+ // }
767
+ // /* -------------------------------------------------------------------------- */
768
+ // /* LOCAL FILE MANAGEMENT */
769
+ // /* -------------------------------------------------------------------------- */
770
+ // const loadLocalTheme = async (): Promise<ProjectData | null> => {
771
+ // try {
772
+ // const response = await fetch('/funui.json', {
773
+ // cache: 'no-cache',
774
+ // })
775
+ // if (response.ok) {
776
+ // const data = await response.json()
777
+ // return data
778
+ // }
779
+ // } catch (error) {
780
+ // console.log('ℹ️ No local theme file found')
781
+ // }
782
+ // return null
783
+ // }
784
+ // /* -------------------------------------------------------------------------- */
785
+ // /* CDN THEME LOADER */
786
+ // /* -------------------------------------------------------------------------- */
787
+ // const loadThemeFromCDN = async (projectId: string): Promise<ProjectData | null> => {
788
+ // if (!projectId) {
789
+ // console.error('❌ No project ID provided for CDN loading')
790
+ // return null
791
+ // }
792
+ // // Try Firebase Storage public URL
793
+ // try {
794
+ // const publicUrl = `https://firebasestorage.googleapis.com/v0/b/funui-4bcd1.firebasestorage.app/o/themes%2F${projectId}.json?alt=media`
795
+ // const response = await fetch(publicUrl, {
796
+ // cache: 'no-cache',
797
+ // })
798
+ // if (response.ok) {
799
+ // const data = await response.json()
800
+ // return data
801
+ // } else {
802
+ // console.error('❌ Firebase Storage fetch failed:', response.status, response.statusText)
803
+ // }
804
+ // } catch (error) {
805
+ // console.error('❌ Error loading from Firebase Storage:', error)
806
+ // }
807
+ // return null
808
+ // }
809
+ // /* -------------------------------------------------------------------------- */
810
+ // /* CSS VARIABLE APPLIER */
811
+ // /* -------------------------------------------------------------------------- */
812
+ // const applyTypographyVariables = (typography: Record<string, string>, root: HTMLElement) => {
813
+ // if (!typography) return
814
+ // Object.entries(typography).forEach(([key, value]) => {
815
+ // const cssVarName = `--${key.replace(/_/g, '-')}`
816
+ // root.style.setProperty(cssVarName, value)
817
+ // })
818
+ // }
819
+ // const applyColorVariables = (colors: Record<string, string>, root: HTMLElement) => {
820
+ // if (!colors) return
821
+ // Object.entries(colors).forEach(([key, value]) => {
822
+ // const cssVarName = `--${key.replace(/_/g, '-')}`
823
+ // root.style.setProperty(cssVarName, value)
824
+ // })
825
+ // }
826
+ // const applyThemeConfig = (themeConfig: Record<string, any>, root: HTMLElement) => {
827
+ // if (!themeConfig) return
828
+ // if (themeConfig.colors) {
829
+ // applyColorVariables(themeConfig.colors, root)
830
+ // }
831
+ // if (themeConfig.typography) {
832
+ // applyTypographyVariables(themeConfig.typography, root)
833
+ // }
834
+ // Object.entries(themeConfig).forEach(([key, value]) => {
835
+ // if (key !== 'colors' && key !== 'typography' && typeof value === 'string') {
836
+ // const cssVarName = `--${key.replace(/_/g, '-')}`
837
+ // root.style.setProperty(cssVarName, value)
838
+ // }
839
+ // })
840
+ // }
841
+ // /* -------------------------------------------------------------------------- */
842
+ // /* VARIABLES HELPER */
843
+ // /* -------------------------------------------------------------------------- */
844
+ // let cachedProjectData: ProjectData | null = null
845
+ // export const getVariable = (name: string): { name: string; value: any } | undefined => {
846
+ // if (!cachedProjectData?.variables) {
847
+ // console.warn('No variables available. Make sure ThemeProvider is mounted.')
848
+ // return undefined
849
+ // }
850
+ // const variable = cachedProjectData.variables.find(v => v.name === name)
851
+ // return variable
852
+ // }
853
+ // export const getAllVariables = (): Variable[] => {
854
+ // return cachedProjectData?.variables || []
855
+ // }
856
+ // /* -------------------------------------------------------------------------- */
857
+ // /* COMPONENT */
858
+ // /* -------------------------------------------------------------------------- */
859
+ // const ThemeProvider: React.FC<ThemeProviderProps> = ({
860
+ // theme,
861
+ // children,
862
+ // funcss = '',
863
+ // minHeight = '100vh',
864
+ // projectId,
865
+ // }) => {
866
+ // const [variant, setVariant] = useState<ThemeVariant>('standard')
867
+ // const [themeConfig, setThemeConfig] = useState<ThemeConfig>({})
868
+ // const [projectData, setProjectData] = useState<ProjectData | null>(null)
869
+ // const [isLoading, setIsLoading] = useState(true)
870
+ // const [isInitialLoad, setIsInitialLoad] = useState(true)
871
+ // const [error, setError] = useState<string | null>(null)
872
+ // const [currentVersion, setCurrentVersion] = useState<number | null>(null)
873
+ // /* -------------------------- Apply base theme --------------------------- */
874
+ // useEffect(() => {
875
+ // const root = document.documentElement
876
+ // const selectedTheme = themes[theme] || themes.light
877
+ // Object.entries(selectedTheme).forEach(([key, value]) => {
878
+ // root.style.setProperty(key, value)
879
+ // })
880
+ // if (
881
+ // ['dark', 'dark-blue', 'midnight-purple', 'cyber-metal'].includes(theme)
882
+ // ) {
883
+ // colorVarsToDarken.forEach((varName) => {
884
+ // const original = getComputedStyle(root)
885
+ // .getPropertyValue(varName)
886
+ // .trim()
887
+ // if (original) {
888
+ // const darkAmount = getDarkenAmount(varName)
889
+ // const rgba = darkenToRgba(original, darkAmount, 0.9)
890
+ // root.style.setProperty(varName, rgba)
891
+ // }
892
+ // })
893
+ // }
894
+ // }, [theme])
895
+ // /* ---------------------- Theme Loading Logic ----------------------- */
896
+ // useEffect(() => {
897
+ // if (typeof window === 'undefined') {
898
+ // setIsLoading(false)
899
+ // setIsInitialLoad(false)
900
+ // return
901
+ // }
902
+ // const root = document.documentElement
903
+ // let pollTimer: NodeJS.Timeout
904
+ // const loadTheme = async () => {
905
+ // try {
906
+ // let finalTheme: ProjectData | null = null
907
+ // let finalVersion: number | null = null
908
+ // // First, try to load local theme
909
+ // const localTheme = await loadLocalTheme()
910
+ // const localVersion = localTheme?.version || 0
911
+ // if (projectId) {
912
+ // // Validate origin access for CDN
913
+ // const hasAccess = await validateOriginAccess(projectId)
914
+ // if (hasAccess) {
915
+ // // Try to load from CDN
916
+ // const cdnTheme = await loadThemeFromCDN(projectId)
917
+ // const cdnVersion = cdnTheme?.version || 0
918
+ // if (cdnTheme) {
919
+ // // CDN theme available - use it
920
+ // finalTheme = cdnTheme
921
+ // finalVersion = cdnVersion
922
+ // if (cdnVersion !== localVersion) {
923
+ // console.log(`🔄 Version mismatch: Local(${localVersion}) vs CDN(${cdnVersion})`)
924
+ // console.log('ℹ️ Using CDN version. Please update your local funui.json file manually.')
925
+ // }
926
+ // } else if (localTheme) {
927
+ // // CDN not available but we have local theme
928
+ // console.log('⚠️ CDN unavailable, using local theme')
929
+ // finalTheme = localTheme
930
+ // finalVersion = localVersion
931
+ // } else {
932
+ // // No theme available anywhere
933
+ // console.warn('⚠️ No theme found (CDN unavailable and no local theme)')
934
+ // setError('Theme not found')
935
+ // }
936
+ // } else {
937
+ // // Origin validation failed
938
+ // if (localTheme) {
939
+ // console.log('⚠️ Origin validation failed, using local theme')
940
+ // finalTheme = localTheme
941
+ // finalVersion = localVersion
942
+ // } else {
943
+ // console.error('❌ Origin validation failed and no local theme available')
944
+ // setError('Access denied and no local theme available')
945
+ // }
946
+ // }
947
+ // } else {
948
+ // // No project ID provided - only use local theme
949
+ // console.log('ℹ️ No project ID provided, using local theme only')
950
+ // if (localTheme) {
951
+ // finalTheme = localTheme
952
+ // finalVersion = localVersion
953
+ // console.log('✅ Theme loaded from local file')
954
+ // } else {
955
+ // console.log('ℹ️ No local theme file found - using base theme only')
956
+ // // No error here - it's valid to use only base theme
957
+ // }
958
+ // }
959
+ // // Apply the theme if we have one
960
+ // if (finalTheme && (!currentVersion || finalVersion !== currentVersion)) {
961
+ // applyThemeData(finalTheme, root)
962
+ // setCurrentVersion(finalVersion)
963
+ // setError(null)
964
+ // } else if (finalTheme) {
965
+ // console.log('✓ Theme up to date')
966
+ // }
967
+ // } catch (err) {
968
+ // console.error('❌ Error loading theme:', err)
969
+ // setError('Failed to load theme')
970
+ // } finally {
971
+ // setIsLoading(false)
972
+ // setIsInitialLoad(false)
973
+ // }
974
+ // }
975
+ // // Initial load
976
+ // loadTheme()
977
+ // // Only poll for updates if we have a project ID
978
+ // if (projectId) {
979
+ // pollTimer = setInterval(() => {
980
+ // loadTheme()
981
+ // }, 5 * 60 * 1000)
982
+ // }
983
+ // return () => {
984
+ // if (pollTimer) {
985
+ // clearInterval(pollTimer)
986
+ // }
987
+ // }
988
+ // }, [projectId, currentVersion, theme])
989
+ // const applyThemeData = (data: ProjectData, root: HTMLElement) => {
990
+ // const themeConfig = data.theme_config ?? {}
991
+ // const newVariant = data.default_variation || 'standard'
992
+ // setVariant(newVariant)
993
+ // setThemeConfig(themeConfig)
994
+ // setProjectData(data)
995
+ // // Cache for variable access
996
+ // cachedProjectData = data
997
+ // // Cache for asset access
998
+ // cachedAssets = data.assets || []
999
+ // // Apply all theme config to CSS variables
1000
+ // applyThemeConfig(themeConfig, root)
1001
+ // }
1002
+ // const contextValue = useMemo(
1003
+ // () => ({
1004
+ // variant,
1005
+ // setVariant,
1006
+ // themeConfig,
1007
+ // projectData,
1008
+ // isLoading,
1009
+ // isInitialLoad,
1010
+ // error,
1011
+ // }),
1012
+ // [variant, themeConfig, projectData, isLoading, isInitialLoad, error]
1013
+ // )
1014
+ // return (
1015
+ // <ThemeContext.Provider value={contextValue}>
1016
+ // <div
1017
+ // className={`theme-${theme} ${funcss}`}
1018
+ // style={{
1019
+ // backgroundColor: 'var(--page-bg)',
1020
+ // color: 'var(--text-color)',
1021
+ // minHeight: minHeight,
1022
+ // transition: isInitialLoad ? 'none' : 'background-color 0.3s ease, color 0.3s ease',
1023
+ // }}
1024
+ // >
1025
+ // {children}
1026
+ // </div>
1027
+ // </ThemeContext.Provider>
1028
+ // )
1029
+ // }
1030
+ // export default ThemeProvider
1031
+ // /* -------------------------------------------------------------------------- */
1032
+ // /* HELPER HOOKS */
1033
+ // /* -------------------------------------------------------------------------- */
1034
+ // export const useThemeValue = (key: string): string | undefined => {
1035
+ // const { themeConfig } = useTheme()
1036
+ // return themeConfig[key]
1037
+ // }
1038
+ // export const useComponentConfig = (componentName: string): any => {
1039
+ // const { projectData } = useTheme()
1040
+ // return projectData?.components?.[componentName] || {}
1041
+ // }
1042
+ // export const useColors = (): Record<string, string> => {
1043
+ // const { projectData } = useTheme()
1044
+ // return projectData?.theme_config?.colors || {}
1045
+ // }
1046
+ // export const useTypography = (): Record<string, string> => {
1047
+ // const { projectData } = useTheme()
1048
+ // return projectData?.theme_config?.typography || {}
1049
+ // }
1050
+ // export const useThemeConfig = (): Record<string, any> => {
1051
+ // const { projectData } = useTheme()
1052
+ // return projectData?.theme_config || {}
1053
+ // }
1054
+ // export const useProjectData = (): ProjectData | null => {
1055
+ // const { projectData } = useTheme()
1056
+ // return projectData
1057
+ // }
1058
+ // export const useColor = (colorName: string): string | undefined => {
1059
+ // const colors = useColors()
1060
+ // return colors[colorName]
1061
+ // }
1062
+ // export const useTypographyValue = (property: string): string | undefined => {
1063
+ // const typography = useTypography()
1064
+ // return typography[property]
1065
+ // }
1066
+ // export const useComponentVariant = (componentName: string, variantName: string = 'default'): any => {
1067
+ // const componentConfig = useComponentConfig(componentName)
1068
+ // return componentConfig[variantName] || {}
1069
+ // }
1070
+ // // Hook to access variables
1071
+ // export const useVariables = (): Variable[] => {
1072
+ // const { projectData } = useTheme()
1073
+ // return projectData?.variables || []
1074
+ // }
1075
+ // // Hook to get a specific variable
1076
+ // export const useVariable = (name: string): any => {
1077
+ // const variables = useVariables()
1078
+ // const variable = variables.find(v => v.name === name)
1079
+ // return variable?.value
1080
+ // }
1081
+ // /* -------------------------------------------------------------------------- */
1082
+ // /* ASSETS HELPER */
1083
+ // /* -------------------------------------------------------------------------- */
1084
+ // interface Asset {
1085
+ // name: string
1086
+ // url: string
1087
+ // file_type: string
1088
+ // }
1089
+ // let cachedAssets: Asset[] = []
1090
+ // export const getAsset = (name: string): Asset | undefined => {
1091
+ // if (!cachedAssets.length) {
1092
+ // console.warn('No assets available. Make sure ThemeProvider is mounted and assets are loaded.')
1093
+ // return undefined
1094
+ // }
1095
+ // const asset = cachedAssets.find(a => a.name === name)
1096
+ // return asset
1097
+ // }
1098
+ // export const getAllAssets = (): Asset[] => {
1099
+ // return cachedAssets
1100
+ // }
1101
+ // export const getAssetValue = (name: string): string | undefined => {
1102
+ // const asset = getAsset(name)
1103
+ // return asset?.url
1104
+ // }
1105
+ // export const getAssetType = (name: string): string | undefined => {
1106
+ // const asset = getAsset(name)
1107
+ // return asset?.file_type
1108
+ // }
1109
+ // export const getAssetInfo = (name: string): { value: string; type: string; name: string } | undefined => {
1110
+ // const asset = getAsset(name)
1111
+ // if (!asset) return undefined
1112
+ // return {
1113
+ // value: asset.url,
1114
+ // type: asset.file_type,
1115
+ // name: asset.name
1116
+ // }
1117
+ // }
1118
+ // // Hook to access all assets
1119
+ // export const useAssets = (): Asset[] => {
1120
+ // const { projectData } = useTheme()
1121
+ // return projectData?.assets || []
1122
+ // }
1123
+ // // Hook to get a specific asset
1124
+ // export const useAsset = (name: string): Asset | undefined => {
1125
+ // const assets = useAssets()
1126
+ // const asset = assets.find(a => a.name === name)
1127
+ // return asset
1128
+ // }
1129
+ // // Hook to get asset URL (most common use case)
1130
+ // export const useAssetValue = (name: string): string | undefined => {
1131
+ // const asset = useAsset(name)
1132
+ // return asset?.url
1133
+ // }
1134
+ // // Hook to get asset type
1135
+ // export const useAssetType = (name: string): string | undefined => {
1136
+ // const asset = useAsset(name)
1137
+ // return asset?.file_type
1138
+ // }
1139
+ // // Hook to get complete asset info
1140
+ // export const useAssetInfo = (name: string): { value: string; type: string; name: string } | undefined => {
1141
+ // const asset = useAsset(name)
1142
+ // if (!asset) return undefined
1143
+ // return {
1144
+ // value: asset.url,
1145
+ // type: asset.file_type,
1146
+ // name: asset.name
1147
+ // }
1148
+ // }
1149
+ // // Hook to filter assets by type
1150
+ // export const useAssetsByType = (type: string): Asset[] => {
1151
+ // const assets = useAssets()
1152
+ // return assets.filter(asset => asset.file_type === type)
1153
+ // }
1154
+ // // Hook to get image assets
1155
+ // export const useImageAssets = (): Asset[] => {
1156
+ // return useAssetsByType('image')
1157
+ // }
1158
+ // // Hook to get video assets
1159
+ // export const useVideoAssets = (): Asset[] => {
1160
+ // return useAssetsByType('video')
1161
+ // }
1162
+ // // Hook to get audio assets
1163
+ // export const useAudioAssets = (): Asset[] => {
1164
+ // return useAssetsByType('audio')
1165
+ // }
1166
+ // // Hook to get document assets
1167
+ // export const useDocumentAssets = (): Asset[] => {
1168
+ // return useAssetsByType('document')
1169
+ // }