funuicss 3.7.16 → 3.8.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/ui/theme/theme.js CHANGED
@@ -70,7 +70,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
70
70
  }
71
71
  };
72
72
  Object.defineProperty(exports, "__esModule", { value: true });
73
- exports.useDocumentAssets = exports.useAudioAssets = exports.useVideoAssets = exports.useImageAssets = exports.useAssetsByType = exports.useAssetInfo = exports.useAssetType = exports.useAssetValue = exports.useAsset = exports.useAssets = exports.getAssetInfo = exports.getAssetType = exports.getAssetValue = exports.getAllAssets = exports.getAsset = exports.useVariable = exports.useVariables = exports.useComponentVariant = exports.useTypographyValue = exports.useColor = exports.useProjectData = exports.useThemeConfig = exports.useTypography = exports.useColors = exports.useComponentConfig = exports.useThemeValue = exports.getAllVariables = exports.getVariable = exports.useVariant = exports.useTheme = void 0;
73
+ exports.getPaginatedRecords = exports.useBucketCache = exports.useAllJsonRecords = exports.usePaginatedRecords = exports.useBucketJsonFiles = exports.useBucketsByCategory = exports.useBucket = exports.useBuckets = exports.useDocumentAssets = exports.useAudioAssets = exports.useVideoAssets = exports.useImageAssets = exports.useAssetsByType = exports.useAssetInfo = exports.useAssetType = exports.useAssetValue = exports.useAsset = exports.useAssets = exports.getAssetInfo = exports.getAssetType = exports.getAssetValue = exports.getAllAssets = exports.getAsset = exports.useVariable = exports.useVariables = exports.useComponentVariant = exports.useTypographyValue = exports.useColor = exports.useProjectData = exports.useThemeConfig = exports.useTypography = exports.useColors = exports.useComponentConfig = exports.useThemeValue = exports.getAllVariables = exports.getVariable = exports.useVariant = exports.useTheme = void 0;
74
74
  var react_1 = __importStar(require("react"));
75
75
  var themes_1 = require("./themes");
76
76
  var darkenUtils_1 = require("./darkenUtils");
@@ -82,6 +82,7 @@ var ThemeContext = (0, react_1.createContext)({
82
82
  isLoading: true,
83
83
  isInitialLoad: true,
84
84
  error: null,
85
+ projectId: undefined,
85
86
  });
86
87
  var useTheme = function () {
87
88
  var context = (0, react_1.useContext)(ThemeContext);
@@ -222,6 +223,95 @@ var loadThemeFromCDN = function (projectId) { return __awaiter(void 0, void 0, v
222
223
  });
223
224
  }); };
224
225
  /* -------------------------------------------------------------------------- */
226
+ /* BUCKET JSON LOADER */
227
+ /* -------------------------------------------------------------------------- */
228
+ var loadBucketJsonFromCDN = function (bucketSanitizedName, projectId, page) { return __awaiter(void 0, void 0, void 0, function () {
229
+ var pageNumber, publicUrl, response, data, error_4;
230
+ return __generator(this, function (_a) {
231
+ switch (_a.label) {
232
+ case 0:
233
+ if (!bucketSanitizedName || !projectId) {
234
+ console.error('❌ Missing parameters for JSON loading');
235
+ return [2 /*return*/, null];
236
+ }
237
+ _a.label = 1;
238
+ case 1:
239
+ _a.trys.push([1, 6, , 7]);
240
+ pageNumber = page.toString();
241
+ publicUrl = "https://firebasestorage.googleapis.com/v0/b/funui-4bcd1.firebasestorage.app/o/projects%2F".concat(projectId, "%2Fbuckets%2F").concat(bucketSanitizedName, "%2F").concat(pageNumber, ".json?alt=media");
242
+ return [4 /*yield*/, fetch(publicUrl, {
243
+ cache: 'no-cache',
244
+ })];
245
+ case 2:
246
+ response = _a.sent();
247
+ if (!response.ok) return [3 /*break*/, 4];
248
+ return [4 /*yield*/, response.json()];
249
+ case 3:
250
+ data = _a.sent();
251
+ console.log(data);
252
+ return [2 /*return*/, data];
253
+ case 4:
254
+ // File might not exist (e.g., page out of range)
255
+ return [2 /*return*/, null];
256
+ case 5: return [3 /*break*/, 7];
257
+ case 6:
258
+ error_4 = _a.sent();
259
+ console.error("\u274C Error loading JSON file for page ".concat(page, ":"), error_4);
260
+ return [2 /*return*/, null];
261
+ case 7: return [2 /*return*/];
262
+ }
263
+ });
264
+ }); };
265
+ var listBucketJsonFiles = function (bucketSanitizedName, projectId) { return __awaiter(void 0, void 0, void 0, function () {
266
+ var files, page, hasMoreFiles, paddedPage, publicUrl, response, error_5;
267
+ return __generator(this, function (_a) {
268
+ switch (_a.label) {
269
+ case 0:
270
+ if (!bucketSanitizedName || !projectId) {
271
+ console.error('❌ Missing parameters for listing JSON files');
272
+ return [2 /*return*/, []];
273
+ }
274
+ _a.label = 1;
275
+ case 1:
276
+ _a.trys.push([1, 5, , 6]);
277
+ files = [];
278
+ page = 1;
279
+ hasMoreFiles = true;
280
+ _a.label = 2;
281
+ case 2:
282
+ if (!(hasMoreFiles && page <= 100)) return [3 /*break*/, 4];
283
+ paddedPage = page.toString().padStart(3, '0');
284
+ publicUrl = "https://firebasestorage.googleapis.com/v0/b/funui-4bcd1.firebasestorage.app/o/projects%2F".concat(projectId, "%2Fbuckets%2F").concat(bucketSanitizedName, "%2Fpage_").concat(paddedPage, ".json?alt=media");
285
+ return [4 /*yield*/, fetch(publicUrl, {
286
+ method: 'HEAD',
287
+ cache: 'no-cache',
288
+ })];
289
+ case 3:
290
+ response = _a.sent();
291
+ if (response.ok) {
292
+ files.push({
293
+ name: "page_".concat(paddedPage, ".json"),
294
+ fullPath: "projects/".concat(projectId, "/buckets/").concat(bucketSanitizedName, "/page_").concat(paddedPage, ".json"),
295
+ url: publicUrl,
296
+ size: parseInt(response.headers.get('content-length') || '0', 10),
297
+ page: page
298
+ });
299
+ page++;
300
+ }
301
+ else {
302
+ hasMoreFiles = false;
303
+ }
304
+ return [3 /*break*/, 2];
305
+ case 4: return [2 /*return*/, files];
306
+ case 5:
307
+ error_5 = _a.sent();
308
+ console.error('❌ Error listing JSON files:', error_5);
309
+ return [2 /*return*/, []];
310
+ case 6: return [2 /*return*/];
311
+ }
312
+ });
313
+ }); };
314
+ /* -------------------------------------------------------------------------- */
225
315
  /* CSS VARIABLE APPLIER */
226
316
  /* -------------------------------------------------------------------------- */
227
317
  var applyTypographyVariables = function (typography, root) {
@@ -277,6 +367,41 @@ var getAllVariables = function () {
277
367
  };
278
368
  exports.getAllVariables = getAllVariables;
279
369
  /* -------------------------------------------------------------------------- */
370
+ /* BUCKET UTILITIES */
371
+ /* -------------------------------------------------------------------------- */
372
+ // Cache for buckets and JSON files
373
+ var cachedBuckets = [];
374
+ var cachedJsonFiles = {};
375
+ var cachedJsonData = {};
376
+ var sanitizeBucketName = function (name) {
377
+ return name
378
+ .trim()
379
+ .replace(/\s+/g, '_')
380
+ .replace(/[^a-zA-Z0-9_-]/g, '')
381
+ .toLowerCase();
382
+ };
383
+ var transformProjectBucket = function (bucket, projectId) {
384
+ return {
385
+ id: bucket.id || bucket._id || '',
386
+ // projectId: bucket.projectId || projectId || '',
387
+ name: bucket.name || '',
388
+ displayName: bucket.displayName || bucket.name || '',
389
+ category: bucket.category || 'uncategorized',
390
+ fields: Array.isArray(bucket.fields) ? bucket.fields : [],
391
+ createdBy: bucket.createdBy || bucket.userId || '',
392
+ createdAt: typeof bucket.createdAt === 'number' ? bucket.createdAt : Date.now(),
393
+ updatedAt: typeof bucket.updatedAt === 'number' ? bucket.updatedAt : Date.now(),
394
+ updatedBy: bucket.updatedBy || bucket.createdBy || '',
395
+ recordCount: bucket.recordCount || 0,
396
+ jsonFilesCount: bucket.jsonFilesCount || 0,
397
+ totalRecordsInJson: bucket.totalRecordsInJson || 0,
398
+ lastJsonExport: bucket.lastJsonExport,
399
+ userId: bucket.userId,
400
+ createdAtString: bucket.createdAt,
401
+ updatedAtString: bucket.updatedAt
402
+ };
403
+ };
404
+ /* -------------------------------------------------------------------------- */
280
405
  /* COMPONENT */
281
406
  /* -------------------------------------------------------------------------- */
282
407
  var ThemeProvider = function (_a) {
@@ -440,6 +565,11 @@ var ThemeProvider = function (_a) {
440
565
  cachedProjectData = data;
441
566
  // Cache for asset access
442
567
  cachedAssets = data.assets || [];
568
+ // Cache for bucket access
569
+ var projectBuckets = data.buckets || [];
570
+ cachedBuckets = projectBuckets.map(function (bucket) {
571
+ return transformProjectBucket(bucket, data.project_id || '');
572
+ });
443
573
  // Apply all theme config to CSS variables
444
574
  applyThemeConfig(themeConfig, root);
445
575
  };
@@ -451,7 +581,8 @@ var ThemeProvider = function (_a) {
451
581
  isLoading: isLoading,
452
582
  isInitialLoad: isInitialLoad,
453
583
  error: error,
454
- }); }, [variant, themeConfig, projectData, isLoading, isInitialLoad, error]);
584
+ projectId: projectId,
585
+ }); }, [variant, themeConfig, projectData, isLoading, isInitialLoad, error, projectId]);
455
586
  return (react_1.default.createElement(ThemeContext.Provider, { value: contextValue },
456
587
  react_1.default.createElement("div", { className: "theme-".concat(theme, " ").concat(funcss), style: {
457
588
  backgroundColor: 'var(--page-bg)',
@@ -624,546 +755,310 @@ var useDocumentAssets = function () {
624
755
  return (0, exports.useAssetsByType)('document');
625
756
  };
626
757
  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
- // }
758
+ /* -------------------------------------------------------------------------- */
759
+ /* BUCKET HOOKS */
760
+ /* -------------------------------------------------------------------------- */
761
+ // Helper function to get bucket
762
+ var getBucketFromCache = function (bucketIdOrName) {
763
+ if (!cachedBuckets.length) {
764
+ console.warn('No buckets available. Make sure ThemeProvider is mounted.');
765
+ return undefined;
766
+ }
767
+ return cachedBuckets.find(function (b) {
768
+ var _a;
769
+ return b.id === bucketIdOrName ||
770
+ b.name.toLowerCase() === bucketIdOrName.toLowerCase() ||
771
+ ((_a = b.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === bucketIdOrName.toLowerCase();
772
+ });
773
+ };
774
+ // Hook to access all buckets
775
+ var useBuckets = function () {
776
+ var projectData = (0, exports.useTheme)().projectData;
777
+ var _a = (0, react_1.useState)([]), buckets = _a[0], setBuckets = _a[1];
778
+ (0, react_1.useEffect)(function () {
779
+ if (projectData === null || projectData === void 0 ? void 0 : projectData.buckets) {
780
+ var transformedBuckets = projectData.buckets.map(function (bucket) {
781
+ return transformProjectBucket(bucket, projectData.project_id || '');
782
+ });
783
+ setBuckets(transformedBuckets);
784
+ cachedBuckets = transformedBuckets;
785
+ }
786
+ else {
787
+ setBuckets([]);
788
+ }
789
+ }, [projectData]);
790
+ return buckets;
791
+ };
792
+ exports.useBuckets = useBuckets;
793
+ // Hook to get a specific bucket
794
+ var useBucket = function (bucketIdOrName) {
795
+ var buckets = (0, exports.useBuckets)();
796
+ return buckets.find(function (b) {
797
+ var _a;
798
+ return b.id === bucketIdOrName ||
799
+ b.name.toLowerCase() === bucketIdOrName.toLowerCase() ||
800
+ ((_a = b.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === bucketIdOrName.toLowerCase();
801
+ });
802
+ };
803
+ exports.useBucket = useBucket;
804
+ // Hook to get buckets by category
805
+ var useBucketsByCategory = function (category) {
806
+ var buckets = (0, exports.useBuckets)();
807
+ if (category === 'all' || category === 'uncategorized') {
808
+ return buckets.filter(function (b) { return !b.category || b.category === 'uncategorized'; });
809
+ }
810
+ return buckets.filter(function (b) { return b.category === category; });
811
+ };
812
+ exports.useBucketsByCategory = useBucketsByCategory;
813
+ // Hook to get bucket JSON files
814
+ var useBucketJsonFiles = function (bucketIdOrName) {
815
+ var _a = (0, react_1.useState)([]), files = _a[0], setFiles = _a[1];
816
+ var _b = (0, react_1.useState)(true), loading = _b[0], setLoading = _b[1];
817
+ var _c = (0, react_1.useState)(null), error = _c[0], setError = _c[1];
818
+ var bucket = (0, exports.useBucket)(bucketIdOrName);
819
+ var projectId = (0, exports.useTheme)().projectId;
820
+ var loadFiles = (0, react_1.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {
821
+ var bucketSanitizedName, jsonFiles, cacheKey, err_2;
822
+ return __generator(this, function (_a) {
823
+ switch (_a.label) {
824
+ case 0:
825
+ if (!bucket || !projectId) {
826
+ setFiles([]);
827
+ setLoading(false);
828
+ return [2 /*return*/];
829
+ }
830
+ _a.label = 1;
831
+ case 1:
832
+ _a.trys.push([1, 3, 4, 5]);
833
+ setLoading(true);
834
+ setError(null);
835
+ bucketSanitizedName = sanitizeBucketName(bucket.displayName || bucket.name);
836
+ return [4 /*yield*/, listBucketJsonFiles(bucketSanitizedName, projectId)];
837
+ case 2:
838
+ jsonFiles = _a.sent();
839
+ setFiles(jsonFiles);
840
+ cacheKey = "".concat(bucket.id, "_").concat(projectId);
841
+ cachedJsonFiles[cacheKey] = jsonFiles;
842
+ return [3 /*break*/, 5];
843
+ case 3:
844
+ err_2 = _a.sent();
845
+ console.error('Error loading JSON files:', err_2);
846
+ setError(err_2 instanceof Error ? err_2.message : 'Failed to load JSON files');
847
+ return [3 /*break*/, 5];
848
+ case 4:
849
+ setLoading(false);
850
+ return [7 /*endfinally*/];
851
+ case 5: return [2 /*return*/];
852
+ }
853
+ });
854
+ }); }, [bucket, projectId]);
855
+ (0, react_1.useEffect)(function () {
856
+ loadFiles();
857
+ }, [loadFiles]);
858
+ return {
859
+ files: files,
860
+ loading: loading,
861
+ error: error,
862
+ refresh: loadFiles
863
+ };
864
+ };
865
+ exports.useBucketJsonFiles = useBucketJsonFiles;
866
+ // Hook to get paginated records (YOU ONLY NEED TO PASS PAGE NUMBER!)
867
+ var usePaginatedRecords = function (bucketIdOrName, page, pageSize) {
868
+ var _a = (0, react_1.useState)([]), records = _a[0], setRecords = _a[1];
869
+ var _b = (0, react_1.useState)(null), metadata = _b[0], setMetadata = _b[1];
870
+ var _c = (0, react_1.useState)(true), loading = _c[0], setLoading = _c[1];
871
+ var _d = (0, react_1.useState)(null), error = _d[0], setError = _d[1];
872
+ var bucket = (0, exports.useBucket)(bucketIdOrName);
873
+ var projectId = (0, exports.useTheme)().projectId;
874
+ var loadRecords = (0, react_1.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {
875
+ var bucketSanitizedName, jsonData, recordsToSet, cacheKey, err_3;
876
+ return __generator(this, function (_a) {
877
+ switch (_a.label) {
878
+ case 0:
879
+ if (!bucket || !projectId) {
880
+ setRecords([]);
881
+ setMetadata(null);
882
+ setLoading(false);
883
+ return [2 /*return*/];
884
+ }
885
+ _a.label = 1;
886
+ case 1:
887
+ _a.trys.push([1, 3, 4, 5]);
888
+ setLoading(true);
889
+ setError(null);
890
+ bucketSanitizedName = sanitizeBucketName(bucket.displayName || bucket.name);
891
+ return [4 /*yield*/, loadBucketJsonFromCDN(bucketSanitizedName, projectId, page)];
892
+ case 2:
893
+ jsonData = _a.sent();
894
+ if (jsonData) {
895
+ recordsToSet = jsonData.records || [];
896
+ // If pageSize is specified, limit the records
897
+ if (pageSize && recordsToSet.length > pageSize) {
898
+ recordsToSet = recordsToSet.slice(0, pageSize);
899
+ }
900
+ setRecords(recordsToSet);
901
+ setMetadata(jsonData.metadata);
902
+ cacheKey = "".concat(bucket.id, "_").concat(projectId);
903
+ if (!cachedJsonData[cacheKey]) {
904
+ cachedJsonData[cacheKey] = {};
905
+ }
906
+ cachedJsonData[cacheKey][page] = jsonData;
907
+ }
908
+ else {
909
+ setRecords([]);
910
+ setMetadata(null);
911
+ }
912
+ return [3 /*break*/, 5];
913
+ case 3:
914
+ err_3 = _a.sent();
915
+ console.error("Error loading records for page ".concat(page, ":"), err_3);
916
+ setError(err_3 instanceof Error ? err_3.message : 'Failed to load records');
917
+ return [3 /*break*/, 5];
918
+ case 4:
919
+ setLoading(false);
920
+ return [7 /*endfinally*/];
921
+ case 5: return [2 /*return*/];
922
+ }
923
+ });
924
+ }); }, [bucket, projectId, page, pageSize]);
925
+ (0, react_1.useEffect)(function () {
926
+ loadRecords();
927
+ }, [loadRecords]);
928
+ return {
929
+ records: records,
930
+ metadata: metadata,
931
+ loading: loading,
932
+ error: error,
933
+ refresh: loadRecords
934
+ };
935
+ };
936
+ exports.usePaginatedRecords = usePaginatedRecords;
937
+ // Hook to get all records from JSON files
938
+ var useAllJsonRecords = function (bucketIdOrName) {
939
+ var _a = (0, react_1.useState)([]), records = _a[0], setRecords = _a[1];
940
+ var _b = (0, react_1.useState)(true), loading = _b[0], setLoading = _b[1];
941
+ var _c = (0, react_1.useState)(null), error = _c[0], setError = _c[1];
942
+ var bucket = (0, exports.useBucket)(bucketIdOrName);
943
+ var projectId = (0, exports.useTheme)().projectId;
944
+ var _d = (0, exports.useBucketJsonFiles)(bucketIdOrName), files = _d.files, filesLoading = _d.loading;
945
+ var loadAllRecords = (0, react_1.useCallback)(function () { return __awaiter(void 0, void 0, void 0, function () {
946
+ var allRecords, _i, files_1, file, bucketSanitizedName, jsonData, err_4;
947
+ return __generator(this, function (_a) {
948
+ switch (_a.label) {
949
+ case 0:
950
+ if (!bucket || !projectId || filesLoading) {
951
+ return [2 /*return*/];
952
+ }
953
+ _a.label = 1;
954
+ case 1:
955
+ _a.trys.push([1, 6, 7, 8]);
956
+ setLoading(true);
957
+ setError(null);
958
+ allRecords = [];
959
+ _i = 0, files_1 = files;
960
+ _a.label = 2;
961
+ case 2:
962
+ if (!(_i < files_1.length)) return [3 /*break*/, 5];
963
+ file = files_1[_i];
964
+ bucketSanitizedName = sanitizeBucketName(bucket.displayName || bucket.name);
965
+ return [4 /*yield*/, loadBucketJsonFromCDN(bucketSanitizedName, projectId, file.page)];
966
+ case 3:
967
+ jsonData = _a.sent();
968
+ if (jsonData && jsonData.records) {
969
+ allRecords.push.apply(allRecords, jsonData.records);
970
+ }
971
+ _a.label = 4;
972
+ case 4:
973
+ _i++;
974
+ return [3 /*break*/, 2];
975
+ case 5:
976
+ setRecords(allRecords);
977
+ return [3 /*break*/, 8];
978
+ case 6:
979
+ err_4 = _a.sent();
980
+ console.error('Error loading all records:', err_4);
981
+ setError(err_4 instanceof Error ? err_4.message : 'Failed to load records');
982
+ return [3 /*break*/, 8];
983
+ case 7:
984
+ setLoading(false);
985
+ return [7 /*endfinally*/];
986
+ case 8: return [2 /*return*/];
987
+ }
988
+ });
989
+ }); }, [bucket, projectId, files, filesLoading]);
990
+ (0, react_1.useEffect)(function () {
991
+ if (!filesLoading) {
992
+ loadAllRecords();
993
+ }
994
+ }, [loadAllRecords, filesLoading]);
995
+ return {
996
+ records: records,
997
+ loading: loading || filesLoading,
998
+ error: error,
999
+ refresh: loadAllRecords
1000
+ };
1001
+ };
1002
+ exports.useAllJsonRecords = useAllJsonRecords;
1003
+ // Hook for cache management
1004
+ var useBucketCache = function () {
1005
+ var clearCache = (0, react_1.useCallback)(function (bucketIdOrName) {
1006
+ if (bucketIdOrName) {
1007
+ var bucket = getBucketFromCache(bucketIdOrName);
1008
+ if (bucket) {
1009
+ var projectId = (0, react_1.useContext)(ThemeContext).projectId;
1010
+ if (projectId) {
1011
+ var cacheKey = "".concat(bucket.id, "_").concat(projectId);
1012
+ delete cachedJsonFiles[cacheKey];
1013
+ delete cachedJsonData[cacheKey];
1014
+ }
1015
+ }
1016
+ }
1017
+ else {
1018
+ cachedJsonFiles = {};
1019
+ cachedJsonData = {};
1020
+ }
1021
+ }, []);
1022
+ var refresh = (0, react_1.useCallback)(function () {
1023
+ // This will be handled by the ThemeProvider when project data changes
1024
+ console.log('Buckets will refresh when project data updates');
1025
+ }, []);
1026
+ return {
1027
+ clearCache: clearCache,
1028
+ refresh: refresh
1029
+ };
1030
+ };
1031
+ exports.useBucketCache = useBucketCache;
1032
+ // Helper function to get bucket records (for non-hook usage)
1033
+ var getPaginatedRecords = function (bucketIdOrName, page, pageSize) { return __awaiter(void 0, void 0, void 0, function () {
1034
+ var bucket, projectId, bucketSanitizedName, jsonData, records;
1035
+ return __generator(this, function (_a) {
1036
+ switch (_a.label) {
1037
+ case 0:
1038
+ bucket = getBucketFromCache(bucketIdOrName);
1039
+ if (!bucket) {
1040
+ throw new Error("Bucket not found: ".concat(bucketIdOrName));
1041
+ }
1042
+ projectId = (0, react_1.useContext)(ThemeContext).projectId;
1043
+ if (!projectId) {
1044
+ throw new Error('Project ID not available');
1045
+ }
1046
+ bucketSanitizedName = sanitizeBucketName(bucket.displayName || bucket.name);
1047
+ return [4 /*yield*/, loadBucketJsonFromCDN(bucketSanitizedName, projectId, page)];
1048
+ case 1:
1049
+ jsonData = _a.sent();
1050
+ if (!jsonData) {
1051
+ return [2 /*return*/, { records: [], metadata: null }];
1052
+ }
1053
+ records = jsonData.records || [];
1054
+ if (pageSize && records.length > pageSize) {
1055
+ records = records.slice(0, pageSize);
1056
+ }
1057
+ return [2 /*return*/, {
1058
+ records: records,
1059
+ metadata: jsonData.metadata
1060
+ }];
1061
+ }
1062
+ });
1063
+ }); };
1064
+ exports.getPaginatedRecords = getPaginatedRecords;