@qwickapps/react-framework 1.5.12 → 1.6.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 (65) hide show
  1. package/README.md +23 -0
  2. package/dist/components/blocks/ImageGallery.d.ts +30 -0
  3. package/dist/components/blocks/ImageGallery.d.ts.map +1 -0
  4. package/dist/components/blocks/OptionSelector.d.ts +45 -0
  5. package/dist/components/blocks/OptionSelector.d.ts.map +1 -0
  6. package/dist/components/blocks/index.d.ts +4 -0
  7. package/dist/components/blocks/index.d.ts.map +1 -1
  8. package/dist/components/forms/Captcha.d.ts +33 -28
  9. package/dist/components/forms/Captcha.d.ts.map +1 -1
  10. package/dist/components/forms/FormCheckbox.d.ts +15 -12
  11. package/dist/components/forms/FormCheckbox.d.ts.map +1 -1
  12. package/dist/components/forms/FormField.d.ts +20 -23
  13. package/dist/components/forms/FormField.d.ts.map +1 -1
  14. package/dist/components/forms/FormSelect.d.ts +16 -15
  15. package/dist/components/forms/FormSelect.d.ts.map +1 -1
  16. package/dist/hooks/useBaseProps.d.ts +27 -1172
  17. package/dist/hooks/useBaseProps.d.ts.map +1 -1
  18. package/dist/index.esm.js +1674 -554
  19. package/dist/index.js +1676 -552
  20. package/dist/palettes/manifest.json +19 -19
  21. package/dist/schemas/CaptchaSchema.d.ts +16 -0
  22. package/dist/schemas/CaptchaSchema.d.ts.map +1 -0
  23. package/dist/schemas/FormCheckboxSchema.d.ts +16 -0
  24. package/dist/schemas/FormCheckboxSchema.d.ts.map +1 -0
  25. package/dist/schemas/FormFieldSchema.d.ts +23 -0
  26. package/dist/schemas/FormFieldSchema.d.ts.map +1 -0
  27. package/dist/schemas/FormSelectSchema.d.ts +20 -0
  28. package/dist/schemas/FormSelectSchema.d.ts.map +1 -0
  29. package/dist/schemas/ImageGallerySchema.d.ts +27 -0
  30. package/dist/schemas/ImageGallerySchema.d.ts.map +1 -0
  31. package/dist/schemas/OptionSelectorSchema.d.ts +34 -0
  32. package/dist/schemas/OptionSelectorSchema.d.ts.map +1 -0
  33. package/dist/schemas/index.d.ts +6 -0
  34. package/dist/schemas/index.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/blocks/Article.tsx +1 -1
  37. package/src/components/blocks/ImageGallery.tsx +464 -0
  38. package/src/components/blocks/OptionSelector.tsx +459 -0
  39. package/src/components/blocks/index.ts +4 -0
  40. package/src/components/forms/Captcha.tsx +57 -63
  41. package/src/components/forms/FormCheckbox.tsx +35 -43
  42. package/src/components/forms/FormField.tsx +50 -66
  43. package/src/components/forms/FormSelect.tsx +41 -49
  44. package/src/hooks/useBaseProps.ts +34 -1
  45. package/src/schemas/CaptchaSchema.ts +65 -0
  46. package/src/schemas/FormCheckboxSchema.ts +65 -0
  47. package/src/schemas/FormFieldSchema.ts +140 -0
  48. package/src/schemas/FormSelectSchema.ts +108 -0
  49. package/src/schemas/ImageGallerySchema.ts +148 -0
  50. package/src/schemas/OptionSelectorSchema.ts +216 -0
  51. package/src/schemas/index.ts +6 -0
  52. package/src/stories/ImageGallery.stories.tsx +497 -0
  53. package/src/stories/OptionSelector.stories.tsx +506 -0
  54. /package/dist/palettes/{palette-autumn.1.5.12.css → palette-autumn.1.6.0.css} +0 -0
  55. /package/dist/palettes/{palette-autumn.1.5.12.min.css → palette-autumn.1.6.0.min.css} +0 -0
  56. /package/dist/palettes/{palette-cosmic.1.5.12.css → palette-cosmic.1.6.0.css} +0 -0
  57. /package/dist/palettes/{palette-cosmic.1.5.12.min.css → palette-cosmic.1.6.0.min.css} +0 -0
  58. /package/dist/palettes/{palette-default.1.5.12.css → palette-default.1.6.0.css} +0 -0
  59. /package/dist/palettes/{palette-default.1.5.12.min.css → palette-default.1.6.0.min.css} +0 -0
  60. /package/dist/palettes/{palette-ocean.1.5.12.css → palette-ocean.1.6.0.css} +0 -0
  61. /package/dist/palettes/{palette-ocean.1.5.12.min.css → palette-ocean.1.6.0.min.css} +0 -0
  62. /package/dist/palettes/{palette-spring.1.5.12.css → palette-spring.1.6.0.css} +0 -0
  63. /package/dist/palettes/{palette-spring.1.5.12.min.css → palette-spring.1.6.0.min.css} +0 -0
  64. /package/dist/palettes/{palette-winter.1.5.12.css → palette-winter.1.6.0.css} +0 -0
  65. /package/dist/palettes/{palette-winter.1.5.12.min.css → palette-winter.1.6.0.min.css} +0 -0
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
- import { useMediaQuery, Box, useTheme as useTheme$1, Paper, Typography, Tooltip, IconButton, Snackbar, Alert, CircularProgress, Button as Button$1, Container as Container$9, Stack, Skeleton, Avatar, Chip, Menu as Menu$1, MenuItem, Card, CardContent, ButtonGroup, Collapse, TextField as TextField$1, FormControl, InputLabel, Select, FormHelperText, FormControlLabel, Switch, Grid, Divider, Link, ListItemIcon, ListItemText, Dialog as Dialog$1, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, DialogActions as DialogActions$1, DialogContentText as DialogContentText$1, Input as Input$5, InputAdornment, Checkbox } from '@mui/material';
3
+ import { useMediaQuery, Box, useTheme as useTheme$1, Paper, Typography, Tooltip, IconButton, Snackbar, Alert, CircularProgress, Button as Button$1, Container as Container$9, Stack, Skeleton, Avatar, Chip, Menu as Menu$1, MenuItem, Card, CardContent, ButtonGroup, Collapse, TextField as TextField$1, FormControl, InputLabel, Select, FormHelperText, FormControlLabel, Switch, Grid, Divider, Link, Modal, ListItemIcon, ListItemText, Dialog as Dialog$1, DialogTitle as DialogTitle$1, DialogContent as DialogContent$1, DialogActions as DialogActions$1, DialogContentText as DialogContentText$1, Input as Input$5, InputAdornment, Checkbox } from '@mui/material';
4
4
  import React, { useMemo, useContext, useState, useCallback, useEffect, createContext, useReducer, useRef, isValidElement, createElement, useId, useLayoutEffect, Component, cloneElement } from 'react';
5
5
  import { MustacheTemplateProvider, MemoryCacheProvider, CachedDataProvider, Field, Editor, FieldType, Schema, Model, DataType } from '@qwickapps/schema';
6
6
  import { createTheme, ThemeProvider as ThemeProvider$1 } from '@mui/material/styles';
@@ -106,6 +106,9 @@ import Warning$3 from '@mui/icons-material/Warning';
106
106
  import { IsOptional, ValidateIf, IsIn, IsInt, Min, IsString, IsBoolean, IsArray, ValidateNested, IsUrl, IsNumber, IsObject, IsNotEmpty, Max } from 'class-validator';
107
107
  import { Type } from 'class-transformer';
108
108
  import 'reflect-metadata';
109
+ import ZoomInIcon from '@mui/icons-material/ZoomIn';
110
+ import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
111
+ import ChevronRightIcon from '@mui/icons-material/ChevronRight';
109
112
  import { useInRouterContext, useNavigate, useLocation } from 'react-router-dom';
110
113
 
111
114
  /**
@@ -18947,281 +18950,283 @@ function ArticleView({
18947
18950
  ...htmlProps,
18948
18951
  ...otherProps,
18949
18952
  ...styleProps,
18950
- // Modern article layout
18951
- maxWidth: '900px',
18952
- mx: 'auto',
18953
- px: {
18954
- xs: 2,
18955
- sm: 3,
18956
- md: 4
18957
- },
18958
- py: {
18959
- xs: 3,
18960
- md: 5
18961
- },
18962
- // Typography - Modern, readable hierarchy
18963
- '& h1, & h2, & h3, & h4, & h5, & h6': {
18964
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
18965
- fontWeight: 700,
18966
- letterSpacing: '-0.02em',
18967
- color: 'var(--theme-text)',
18968
- scrollMarginTop: '100px',
18969
- // For anchor links
18970
- '&:first-of-type': {
18971
- mt: 0
18972
- }
18973
- },
18974
- '& h1': {
18975
- fontSize: {
18976
- xs: '2rem',
18977
- md: '2.75rem'
18953
+ sx: {
18954
+ // Modern article layout
18955
+ maxWidth: '900px',
18956
+ mx: 'auto',
18957
+ px: {
18958
+ xs: 2,
18959
+ sm: 3,
18960
+ md: 4
18978
18961
  },
18979
- lineHeight: 1.15,
18980
- mb: 3,
18981
- mt: 5
18982
- },
18983
- '& h2': {
18984
- fontSize: {
18985
- xs: '1.5rem',
18986
- md: '2rem'
18962
+ py: {
18963
+ xs: 3,
18964
+ md: 5
18987
18965
  },
18988
- lineHeight: 1.25,
18989
- mb: 2.5,
18990
- mt: 5,
18991
- pb: 1.5,
18992
- borderBottom: '1px solid var(--theme-border-lighter)'
18993
- },
18994
- '& h3': {
18995
- fontSize: {
18996
- xs: '1.25rem',
18997
- md: '1.5rem'
18966
+ // Typography - Modern, readable hierarchy
18967
+ '& h1, & h2, & h3, & h4, & h5, & h6': {
18968
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
18969
+ fontWeight: 700,
18970
+ letterSpacing: '-0.02em',
18971
+ color: 'var(--theme-text)',
18972
+ scrollMarginTop: '100px',
18973
+ // For anchor links
18974
+ '&:first-of-type': {
18975
+ mt: 0
18976
+ }
18998
18977
  },
18999
- lineHeight: 1.3,
19000
- mb: 2,
19001
- mt: 4
19002
- },
19003
- '& h4': {
19004
- fontSize: {
19005
- xs: '1.1rem',
19006
- md: '1.25rem'
18978
+ '& h1': {
18979
+ fontSize: {
18980
+ xs: '2rem',
18981
+ md: '2.75rem'
18982
+ },
18983
+ lineHeight: 1.15,
18984
+ mb: 3,
18985
+ mt: 5
19007
18986
  },
19008
- lineHeight: 1.4,
19009
- mb: 1.5,
19010
- mt: 3,
19011
- color: 'var(--theme-text)',
19012
- fontWeight: 600
19013
- },
19014
- // Body text - Optimized for reading
19015
- '& p': {
19016
- fontSize: {
19017
- xs: '1rem',
19018
- md: '1.0625rem'
18987
+ '& h2': {
18988
+ fontSize: {
18989
+ xs: '1.5rem',
18990
+ md: '2rem'
18991
+ },
18992
+ lineHeight: 1.25,
18993
+ mb: 2.5,
18994
+ mt: 5,
18995
+ pb: 1.5,
18996
+ borderBottom: '1px solid var(--theme-border-lighter)'
19019
18997
  },
19020
- lineHeight: 1.75,
19021
- mb: 2,
19022
- color: 'var(--theme-text)',
19023
- fontFamily: 'Georgia, "Times New Roman", serif',
19024
- '&:last-child': {
19025
- mb: 0
19026
- }
19027
- },
19028
- // Lists - Better visual hierarchy
19029
- '& ul, & ol': {
19030
- mb: 3,
19031
- pl: {
19032
- xs: 3,
19033
- md: 4
18998
+ '& h3': {
18999
+ fontSize: {
19000
+ xs: '1.25rem',
19001
+ md: '1.5rem'
19002
+ },
19003
+ lineHeight: 1.3,
19004
+ mb: 2,
19005
+ mt: 4
19006
+ },
19007
+ '& h4': {
19008
+ fontSize: {
19009
+ xs: '1.1rem',
19010
+ md: '1.25rem'
19011
+ },
19012
+ lineHeight: 1.4,
19013
+ mb: 1.5,
19014
+ mt: 3,
19015
+ color: 'var(--theme-text)',
19016
+ fontWeight: 600
19034
19017
  },
19035
- '& li': {
19036
- mb: 1.25,
19037
- lineHeight: 1.7,
19018
+ // Body text - Optimized for reading
19019
+ '& p': {
19038
19020
  fontSize: {
19039
19021
  xs: '1rem',
19040
19022
  md: '1.0625rem'
19041
19023
  },
19024
+ lineHeight: 1.75,
19025
+ mb: 2,
19042
19026
  color: 'var(--theme-text)',
19043
19027
  fontFamily: 'Georgia, "Times New Roman", serif',
19044
- '&::marker': {
19045
- color: 'var(--theme-primary)',
19046
- fontWeight: 600
19047
- },
19048
- '& p': {
19049
- mb: 0.5
19028
+ '&:last-child': {
19029
+ mb: 0
19050
19030
  }
19051
19031
  },
19032
+ // Lists - Better visual hierarchy
19052
19033
  '& ul, & ol': {
19053
- mt: 1,
19054
- mb: 0
19055
- }
19056
- },
19057
- // Code blocks - Modern syntax highlighting style
19058
- '& pre': {
19059
- backgroundColor: 'var(--theme-surface-elevated)',
19060
- color: 'var(--theme-text)',
19061
- borderRadius: 'var(--theme-border-radius)',
19062
- p: {
19063
- xs: 2,
19064
- md: 3
19065
- },
19066
- mb: 3,
19067
- overflow: 'auto',
19068
- fontSize: '0.9rem',
19069
- lineHeight: 1.6,
19070
- fontFamily: '"Fira Code", "Cascadia Code", "SF Mono", Monaco, Consolas, monospace',
19071
- border: '1px solid var(--theme-border-light)',
19072
- boxShadow: 'var(--theme-elevation-2)',
19073
- '& code': {
19074
- backgroundColor: 'transparent',
19075
- color: 'inherit',
19076
- padding: 0,
19077
- fontSize: 'inherit',
19078
- fontFamily: 'inherit'
19079
- }
19080
- },
19081
- // Inline code - Subtle highlight
19082
- '& code': {
19083
- backgroundColor: 'var(--theme-code-bg)',
19084
- color: 'var(--theme-error)',
19085
- padding: '0.2em 0.4em',
19086
- borderRadius: 'var(--theme-border-radius-small)',
19087
- fontSize: '0.9em',
19088
- fontFamily: '"Fira Code", "Cascadia Code", "SF Mono", Monaco, Consolas, monospace',
19089
- fontWeight: 500
19090
- },
19091
- // Blockquotes - Elegant callouts
19092
- '& blockquote': {
19093
- borderLeft: '4px solid var(--theme-primary)',
19094
- backgroundColor: 'var(--theme-surface-variant)',
19095
- borderRadius: `0 var(--theme-border-radius-small) var(--theme-border-radius-small) 0`,
19096
- pl: 3,
19097
- pr: 3,
19098
- py: 2.5,
19099
- my: 4,
19100
- ml: 0,
19101
- mr: 0,
19102
- '& p': {
19103
- fontSize: {
19104
- xs: '1.05rem',
19105
- md: '1.125rem'
19034
+ mb: 3,
19035
+ pl: {
19036
+ xs: 3,
19037
+ md: 4
19106
19038
  },
19107
- fontStyle: 'italic',
19108
- lineHeight: 1.6,
19109
- mb: 1.5,
19110
- color: 'var(--theme-text)',
19111
- '&:last-child': {
19039
+ '& li': {
19040
+ mb: 1.25,
19041
+ lineHeight: 1.7,
19042
+ fontSize: {
19043
+ xs: '1rem',
19044
+ md: '1.0625rem'
19045
+ },
19046
+ color: 'var(--theme-text)',
19047
+ fontFamily: 'Georgia, "Times New Roman", serif',
19048
+ '&::marker': {
19049
+ color: 'var(--theme-primary)',
19050
+ fontWeight: 600
19051
+ },
19052
+ '& p': {
19053
+ mb: 0.5
19054
+ }
19055
+ },
19056
+ '& ul, & ol': {
19057
+ mt: 1,
19112
19058
  mb: 0
19113
19059
  }
19114
19060
  },
19115
- '& cite': {
19116
- display: 'block',
19117
- fontSize: '0.9rem',
19118
- fontStyle: 'normal',
19119
- fontWeight: 500,
19061
+ // Code blocks - Modern syntax highlighting style
19062
+ '& pre': {
19063
+ backgroundColor: 'var(--theme-surface-elevated)',
19120
19064
  color: 'var(--theme-text)',
19121
- mt: 1,
19122
- '&::before': {
19123
- content: '"— "',
19124
- color: 'var(--theme-primary)'
19065
+ borderRadius: 'var(--theme-border-radius)',
19066
+ p: {
19067
+ xs: 2,
19068
+ md: 3
19069
+ },
19070
+ mb: 3,
19071
+ overflow: 'auto',
19072
+ fontSize: '0.9rem',
19073
+ lineHeight: 1.6,
19074
+ fontFamily: '"Fira Code", "Cascadia Code", "SF Mono", Monaco, Consolas, monospace',
19075
+ border: '1px solid var(--theme-border-light)',
19076
+ boxShadow: 'var(--theme-elevation-2)',
19077
+ '& code': {
19078
+ backgroundColor: 'transparent',
19079
+ color: 'inherit',
19080
+ padding: 0,
19081
+ fontSize: 'inherit',
19082
+ fontFamily: 'inherit'
19125
19083
  }
19126
- }
19127
- },
19128
- // Tables - Clean, modern design
19129
- '& table': {
19130
- width: '100%',
19131
- borderCollapse: 'separate',
19132
- borderSpacing: 0,
19133
- mb: 3,
19134
- fontSize: '0.95rem',
19135
- overflow: 'hidden',
19136
- borderRadius: 'var(--theme-border-radius-small)',
19137
- border: '1px solid var(--theme-border-light)',
19138
- '& thead': {
19084
+ },
19085
+ // Inline code - Subtle highlight
19086
+ '& code': {
19087
+ backgroundColor: 'var(--theme-code-bg)',
19088
+ color: 'var(--theme-error)',
19089
+ padding: '0.2em 0.4em',
19090
+ borderRadius: 'var(--theme-border-radius-small)',
19091
+ fontSize: '0.9em',
19092
+ fontFamily: '"Fira Code", "Cascadia Code", "SF Mono", Monaco, Consolas, monospace',
19093
+ fontWeight: 500
19094
+ },
19095
+ // Blockquotes - Elegant callouts
19096
+ '& blockquote': {
19097
+ borderLeft: '4px solid var(--theme-primary)',
19139
19098
  backgroundColor: 'var(--theme-surface-variant)',
19140
- '& th': {
19141
- padding: '12px 16px',
19142
- textAlign: 'left',
19143
- fontWeight: 600,
19099
+ borderRadius: `0 var(--theme-border-radius-small) var(--theme-border-radius-small) 0`,
19100
+ pl: 3,
19101
+ pr: 3,
19102
+ py: 2.5,
19103
+ my: 4,
19104
+ ml: 0,
19105
+ mr: 0,
19106
+ '& p': {
19107
+ fontSize: {
19108
+ xs: '1.05rem',
19109
+ md: '1.125rem'
19110
+ },
19111
+ fontStyle: 'italic',
19112
+ lineHeight: 1.6,
19113
+ mb: 1.5,
19144
19114
  color: 'var(--theme-text)',
19145
- borderBottom: '2px solid var(--theme-border-main)',
19146
- fontSize: '0.875rem',
19147
- textTransform: 'uppercase',
19148
- letterSpacing: '0.05em'
19115
+ '&:last-child': {
19116
+ mb: 0
19117
+ }
19118
+ },
19119
+ '& cite': {
19120
+ display: 'block',
19121
+ fontSize: '0.9rem',
19122
+ fontStyle: 'normal',
19123
+ fontWeight: 500,
19124
+ color: 'var(--theme-text)',
19125
+ mt: 1,
19126
+ '&::before': {
19127
+ content: '"— "',
19128
+ color: 'var(--theme-primary)'
19129
+ }
19149
19130
  }
19150
19131
  },
19151
- '& tbody': {
19152
- '& tr': {
19153
- borderBottom: '1px solid var(--theme-border-lighter)',
19154
- transition: 'background-color 0.2s ease',
19155
- '&:hover': {
19156
- backgroundColor: 'var(--theme-surface-variant)'
19132
+ // Tables - Clean, modern design
19133
+ '& table': {
19134
+ width: '100%',
19135
+ borderCollapse: 'separate',
19136
+ borderSpacing: 0,
19137
+ mb: 3,
19138
+ fontSize: '0.95rem',
19139
+ overflow: 'hidden',
19140
+ borderRadius: 'var(--theme-border-radius-small)',
19141
+ border: '1px solid var(--theme-border-light)',
19142
+ '& thead': {
19143
+ backgroundColor: 'var(--theme-surface-variant)',
19144
+ '& th': {
19145
+ padding: '12px 16px',
19146
+ textAlign: 'left',
19147
+ fontWeight: 600,
19148
+ color: 'var(--theme-text)',
19149
+ borderBottom: '2px solid var(--theme-border-main)',
19150
+ fontSize: '0.875rem',
19151
+ textTransform: 'uppercase',
19152
+ letterSpacing: '0.05em'
19153
+ }
19154
+ },
19155
+ '& tbody': {
19156
+ '& tr': {
19157
+ borderBottom: '1px solid var(--theme-border-lighter)',
19158
+ transition: 'background-color 0.2s ease',
19159
+ '&:hover': {
19160
+ backgroundColor: 'var(--theme-surface-variant)'
19161
+ },
19162
+ '&:last-child': {
19163
+ borderBottom: 'none'
19164
+ }
19157
19165
  },
19158
- '&:last-child': {
19159
- borderBottom: 'none'
19166
+ '& td': {
19167
+ padding: '12px 16px',
19168
+ color: 'var(--theme-text)',
19169
+ lineHeight: 1.6
19160
19170
  }
19171
+ }
19172
+ },
19173
+ // Text emphasis
19174
+ '& strong': {
19175
+ fontWeight: 700,
19176
+ color: 'var(--theme-text)'
19177
+ },
19178
+ '& em': {
19179
+ fontStyle: 'italic',
19180
+ color: 'var(--theme-text)'
19181
+ },
19182
+ // Links - Modern, accessible
19183
+ '& a': {
19184
+ color: 'var(--theme-primary)',
19185
+ textDecoration: 'none',
19186
+ fontWeight: 500,
19187
+ borderBottom: '1px solid transparent',
19188
+ transition: 'border-color 0.2s ease',
19189
+ '&:hover': {
19190
+ borderBottomColor: 'var(--theme-primary)'
19161
19191
  },
19162
- '& td': {
19163
- padding: '12px 16px',
19164
- color: 'var(--theme-text)',
19165
- lineHeight: 1.6
19192
+ '&:focus-visible': {
19193
+ outline: '2px solid var(--theme-primary)',
19194
+ outlineOffset: '2px',
19195
+ borderRadius: '2px'
19166
19196
  }
19167
- }
19168
- },
19169
- // Text emphasis
19170
- '& strong': {
19171
- fontWeight: 700,
19172
- color: 'var(--theme-text)'
19173
- },
19174
- '& em': {
19175
- fontStyle: 'italic',
19176
- color: 'var(--theme-text)'
19177
- },
19178
- // Links - Modern, accessible
19179
- '& a': {
19180
- color: 'var(--theme-primary)',
19181
- textDecoration: 'none',
19182
- fontWeight: 500,
19183
- borderBottom: '1px solid transparent',
19184
- transition: 'border-color 0.2s ease',
19185
- '&:hover': {
19186
- borderBottomColor: 'var(--theme-primary)'
19187
19197
  },
19188
- '&:focus-visible': {
19189
- outline: '2px solid var(--theme-primary)',
19190
- outlineOffset: '2px',
19191
- borderRadius: '2px'
19192
- }
19193
- },
19194
- // Images and figures
19195
- '& img': {
19196
- maxWidth: '100%',
19197
- height: 'auto',
19198
- borderRadius: 'var(--theme-border-radius-small)',
19199
- display: 'block',
19200
- my: 3
19201
- },
19202
- '& figure': {
19203
- margin: '3rem 0',
19198
+ // Images and figures
19204
19199
  '& img': {
19205
19200
  maxWidth: '100%',
19206
19201
  height: 'auto',
19207
19202
  borderRadius: 'var(--theme-border-radius-small)',
19208
- boxShadow: 'var(--theme-elevation-2)'
19203
+ display: 'block',
19204
+ my: 3
19209
19205
  },
19210
- '& figcaption': {
19211
- textAlign: 'center',
19212
- fontSize: '0.875rem',
19213
- color: 'var(--theme-text)',
19214
- mt: 1.5,
19215
- fontStyle: 'italic'
19216
- }
19217
- },
19218
- // Horizontal rules
19219
- '& hr': {
19220
- border: 'none',
19221
- borderTop: '1px solid var(--theme-border-light)',
19222
- my: 5
19206
+ '& figure': {
19207
+ margin: '3rem 0',
19208
+ '& img': {
19209
+ maxWidth: '100%',
19210
+ height: 'auto',
19211
+ borderRadius: 'var(--theme-border-radius-small)',
19212
+ boxShadow: 'var(--theme-elevation-2)'
19213
+ },
19214
+ '& figcaption': {
19215
+ textAlign: 'center',
19216
+ fontSize: '0.875rem',
19217
+ color: 'var(--theme-text)',
19218
+ mt: 1.5,
19219
+ fontStyle: 'italic'
19220
+ }
19221
+ },
19222
+ // Horizontal rules
19223
+ '& hr': {
19224
+ border: 'none',
19225
+ borderTop: '1px solid var(--theme-border-light)',
19226
+ my: 5
19227
+ },
19228
+ ...styleProps.sx
19223
19229
  },
19224
- ...styleProps.sx,
19225
19230
  children: html
19226
19231
  });
19227
19232
  }
@@ -21415,105 +21420,734 @@ function ProductCard(props) {
21415
21420
  });
21416
21421
  }
21417
21422
 
21418
- // Default render function based on component type
21419
- const getDefaultRenderItem = (renderComponent = 'ProductCard', itemProps = {}) => {
21420
- return (item, index) => {
21421
- const key = item?.id || item?.key || index;
21422
- switch (renderComponent) {
21423
- case 'ProductCard':
21424
- return jsx(ProductCard, {
21425
- product: item,
21426
- ...itemProps
21427
- }, key);
21428
- case 'FeatureCard':
21429
- return jsx(FeatureCard, {
21430
- feature: item,
21431
- ...itemProps
21432
- }, key);
21433
- case 'Custom':
21434
- default:
21435
- // For custom components, assume the item contains the component data
21436
- return jsx("div", {
21437
- children: JSON.stringify(item)
21438
- }, key);
21439
- }
21440
- };
21441
- };
21442
21423
  // View component - handles the actual rendering
21443
- function CardListGridView({
21444
- items = [],
21445
- renderItem,
21446
- renderComponent = 'ProductCard',
21447
- itemProps = {},
21448
- columns = 2,
21449
- spacing = 'large',
21450
- equalHeight = true,
21424
+ function ImageGalleryView({
21425
+ images = [],
21426
+ productName,
21427
+ variant = 'thumbnails',
21428
+ thumbnailPosition = 'left',
21429
+ aspectRatio = '1',
21430
+ showZoom = true,
21431
+ maxImages,
21432
+ dataSource,
21433
+ bindingOptions,
21451
21434
  ...restProps
21452
21435
  }) {
21453
- const {
21454
- styleProps,
21455
- htmlProps,
21456
- restProps: otherProps
21457
- } = useBaseProps(restProps);
21458
- // Return null if no items and no render function
21459
- if (!items.length && !renderItem) {
21460
- return null;
21461
- }
21462
- // Use provided renderItem or create default based on renderComponent
21463
- const actualRenderItem = renderItem || getDefaultRenderItem(renderComponent, itemProps);
21464
- return jsx(GridLayout, {
21465
- columns: columns,
21466
- spacing: spacing,
21467
- equalHeight: equalHeight,
21468
- ...htmlProps,
21469
- ...styleProps,
21470
- ...otherProps,
21471
- children: items.map((item, index) => actualRenderItem(item, index))
21472
- });
21473
- }
21474
- // Main component with data binding support
21475
- function CardListGrid(props) {
21476
- const {
21477
- dataSource,
21478
- bindingOptions,
21479
- ...restProps
21480
- } = props;
21481
- // Always call hooks unconditionally
21482
- const result = useDataBinding(dataSource || '', restProps);
21483
- // If no dataSource, use traditional props
21484
- if (!dataSource) {
21485
- return jsx(CardListGridView, {
21486
- ...restProps
21487
- });
21488
- }
21489
- // Use data binding result
21490
- const {
21491
- loading,
21492
- error,
21493
- ...cardListGridProps
21494
- } = result;
21495
- // Show loading state
21496
- if (loading) {
21497
- return jsx(GridLayout, {
21498
- columns: restProps.columns || 2,
21499
- spacing: restProps.spacing || 'large',
21500
- style: {
21501
- textAlign: 'center',
21502
- padding: '2rem'
21436
+ const [selectedIndex, setSelectedIndex] = useState(0);
21437
+ const [zoomOpen, setZoomOpen] = useState(false);
21438
+ // Limit images if maxImages is specified
21439
+ const displayImages = maxImages ? images.slice(0, maxImages) : images;
21440
+ const handlePrevious = useCallback(() => {
21441
+ setSelectedIndex(prev => prev === 0 ? displayImages.length - 1 : prev - 1);
21442
+ }, [displayImages.length]);
21443
+ const handleNext = useCallback(() => {
21444
+ setSelectedIndex(prev => prev === displayImages.length - 1 ? 0 : prev + 1);
21445
+ }, [displayImages.length]);
21446
+ const handleThumbnailClick = useCallback(index => {
21447
+ setSelectedIndex(index);
21448
+ }, []);
21449
+ const handleZoomOpen = useCallback(() => {
21450
+ if (showZoom) {
21451
+ setZoomOpen(true);
21452
+ }
21453
+ }, [showZoom]);
21454
+ const handleZoomClose = useCallback(() => {
21455
+ setZoomOpen(false);
21456
+ }, []);
21457
+ // Handle empty images
21458
+ if (!displayImages || displayImages.length === 0) {
21459
+ return jsx(Box, {
21460
+ ...restProps,
21461
+ sx: {
21462
+ backgroundColor: 'var(--theme-surface-variant)',
21463
+ borderRadius: 'var(--theme-border-radius)',
21464
+ display: 'flex',
21465
+ alignItems: 'center',
21466
+ justifyContent: 'center',
21467
+ aspectRatio,
21468
+ minHeight: 400
21503
21469
  },
21504
- children: jsx("div", {
21505
- children: "Loading..."
21470
+ children: jsx(Skeleton, {
21471
+ variant: "rectangular",
21472
+ width: "100%",
21473
+ height: "100%",
21474
+ sx: {
21475
+ borderRadius: 'var(--theme-border-radius)'
21476
+ }
21506
21477
  })
21507
21478
  });
21508
21479
  }
21509
- if (error) {
21510
- console.error('Error loading card list grid:', error);
21511
- {
21512
- return jsx(GridLayout, {
21513
- columns: restProps.columns || 2,
21514
- spacing: restProps.spacing || 'large',
21480
+ const currentImage = displayImages[selectedIndex];
21481
+ // Render thumbnails
21482
+ const renderThumbnails = () => jsx(Box, {
21483
+ sx: {
21484
+ display: 'flex',
21485
+ flexDirection: thumbnailPosition === 'left' || thumbnailPosition === 'right' ? 'column' : 'row',
21486
+ gap: 1,
21487
+ overflow: 'auto',
21488
+ maxHeight: thumbnailPosition === 'left' || thumbnailPosition === 'right' ? 500 : 'auto',
21489
+ maxWidth: thumbnailPosition === 'bottom' ? '100%' : 'auto'
21490
+ },
21491
+ children: displayImages.map((image, index) => jsx(Box, {
21492
+ onClick: () => handleThumbnailClick(index),
21493
+ sx: {
21494
+ width: 80,
21495
+ height: 80,
21496
+ flexShrink: 0,
21497
+ cursor: 'pointer',
21498
+ border: '2px solid',
21499
+ borderColor: index === selectedIndex ? 'var(--theme-primary)' : 'var(--theme-border-main)',
21500
+ borderRadius: 'var(--theme-border-radius-small)',
21501
+ overflow: 'hidden',
21502
+ transition: 'all 0.2s ease-in-out',
21503
+ '&:hover': {
21504
+ borderColor: 'var(--theme-border-emphasis)'
21505
+ }
21506
+ },
21507
+ children: jsx("img", {
21508
+ src: image.thumbnail || image.url,
21509
+ alt: `${productName} thumbnail ${index + 1}`,
21515
21510
  style: {
21516
- textAlign: 'center',
21511
+ width: '100%',
21512
+ height: '100%',
21513
+ objectFit: 'cover'
21514
+ }
21515
+ })
21516
+ }, index))
21517
+ });
21518
+ // Render main image container
21519
+ const renderMainImage = () => jsxs(Box, {
21520
+ sx: {
21521
+ position: 'relative',
21522
+ width: '100%',
21523
+ backgroundColor: 'var(--theme-surface)',
21524
+ borderRadius: 'var(--theme-border-radius)',
21525
+ border: '1px solid var(--theme-border-main)',
21526
+ overflow: 'hidden',
21527
+ aspectRatio
21528
+ },
21529
+ children: [jsx("img", {
21530
+ src: currentImage.url,
21531
+ alt: currentImage.alt || `${productName} - Image ${selectedIndex + 1}`,
21532
+ style: {
21533
+ width: '100%',
21534
+ height: '100%',
21535
+ objectFit: 'contain',
21536
+ display: 'block'
21537
+ }
21538
+ }), showZoom && jsx(IconButton, {
21539
+ onClick: handleZoomOpen,
21540
+ sx: {
21541
+ position: 'absolute',
21542
+ top: 8,
21543
+ right: 8,
21544
+ backgroundColor: 'var(--theme-surface)',
21545
+ color: 'var(--theme-text-primary)',
21546
+ '&:hover': {
21547
+ backgroundColor: 'var(--theme-surface-variant)'
21548
+ }
21549
+ },
21550
+ "aria-label": "Zoom image",
21551
+ children: jsx(ZoomInIcon, {})
21552
+ }), variant === 'carousel' && displayImages.length > 1 && jsxs(Fragment, {
21553
+ children: [jsx(IconButton, {
21554
+ onClick: handlePrevious,
21555
+ sx: {
21556
+ position: 'absolute',
21557
+ left: 8,
21558
+ top: '50%',
21559
+ transform: 'translateY(-50%)',
21560
+ backgroundColor: 'var(--theme-surface)',
21561
+ color: 'var(--theme-text-primary)',
21562
+ '&:hover': {
21563
+ backgroundColor: 'var(--theme-surface-variant)'
21564
+ }
21565
+ },
21566
+ "aria-label": "Previous image",
21567
+ children: jsx(ChevronLeftIcon, {})
21568
+ }), jsx(IconButton, {
21569
+ onClick: handleNext,
21570
+ sx: {
21571
+ position: 'absolute',
21572
+ right: 8,
21573
+ top: '50%',
21574
+ transform: 'translateY(-50%)',
21575
+ backgroundColor: 'var(--theme-surface)',
21576
+ color: 'var(--theme-text-primary)',
21577
+ '&:hover': {
21578
+ backgroundColor: 'var(--theme-surface-variant)'
21579
+ }
21580
+ },
21581
+ "aria-label": "Next image",
21582
+ children: jsx(ChevronRightIcon, {})
21583
+ })]
21584
+ })]
21585
+ });
21586
+ // Render zoom modal
21587
+ const renderZoomModal = () => jsx(Modal, {
21588
+ open: zoomOpen,
21589
+ onClose: handleZoomClose,
21590
+ sx: {
21591
+ display: 'flex',
21592
+ alignItems: 'center',
21593
+ justifyContent: 'center',
21594
+ backgroundColor: 'rgba(0, 0, 0, 0.9)'
21595
+ },
21596
+ children: jsxs(Box, {
21597
+ sx: {
21598
+ position: 'relative',
21599
+ maxWidth: '90vw',
21600
+ maxHeight: '90vh',
21601
+ outline: 'none'
21602
+ },
21603
+ children: [jsx(IconButton, {
21604
+ onClick: handleZoomClose,
21605
+ sx: {
21606
+ position: 'absolute',
21607
+ top: -40,
21608
+ right: 0,
21609
+ color: 'white',
21610
+ '&:hover': {
21611
+ backgroundColor: 'rgba(255, 255, 255, 0.1)'
21612
+ }
21613
+ },
21614
+ "aria-label": "Close zoom",
21615
+ children: jsx(Close, {})
21616
+ }), jsx("img", {
21617
+ src: currentImage.url,
21618
+ alt: currentImage.alt || `${productName} - Zoomed view`,
21619
+ style: {
21620
+ maxWidth: '100%',
21621
+ maxHeight: '90vh',
21622
+ objectFit: 'contain'
21623
+ }
21624
+ })]
21625
+ })
21626
+ });
21627
+ // Render thumbnails variant
21628
+ if (variant === 'thumbnails') {
21629
+ return jsxs(Box, {
21630
+ ...restProps,
21631
+ children: [jsxs(Box, {
21632
+ sx: {
21633
+ display: 'flex',
21634
+ flexDirection: {
21635
+ xs: 'column',
21636
+ sm: thumbnailPosition === 'bottom' ? 'column' : 'row'
21637
+ },
21638
+ gap: 2
21639
+ },
21640
+ children: [thumbnailPosition === 'left' && jsx(Box, {
21641
+ sx: {
21642
+ order: {
21643
+ xs: 2,
21644
+ sm: 1
21645
+ }
21646
+ },
21647
+ children: renderThumbnails()
21648
+ }), jsx(Box, {
21649
+ sx: {
21650
+ flex: 1,
21651
+ order: {
21652
+ xs: 1,
21653
+ sm: thumbnailPosition === 'left' ? 2 : 1
21654
+ }
21655
+ },
21656
+ children: renderMainImage()
21657
+ }), thumbnailPosition === 'right' && jsx(Box, {
21658
+ sx: {
21659
+ order: {
21660
+ xs: 2,
21661
+ sm: 2
21662
+ }
21663
+ },
21664
+ children: renderThumbnails()
21665
+ }), thumbnailPosition === 'bottom' && jsx(Box, {
21666
+ sx: {
21667
+ order: 2
21668
+ },
21669
+ children: renderThumbnails()
21670
+ })]
21671
+ }), renderZoomModal()]
21672
+ });
21673
+ }
21674
+ // Render carousel variant
21675
+ if (variant === 'carousel') {
21676
+ return jsxs(Box, {
21677
+ ...restProps,
21678
+ children: [renderMainImage(), displayImages.length > 1 && jsx(Box, {
21679
+ sx: {
21680
+ display: 'flex',
21681
+ justifyContent: 'center',
21682
+ gap: 1,
21683
+ mt: 2
21684
+ },
21685
+ children: displayImages.map((_, index) => jsx(Box, {
21686
+ onClick: () => handleThumbnailClick(index),
21687
+ sx: {
21688
+ width: 10,
21689
+ height: 10,
21690
+ borderRadius: '50%',
21691
+ backgroundColor: index === selectedIndex ? 'var(--theme-primary)' : 'var(--theme-border-main)',
21692
+ cursor: 'pointer',
21693
+ transition: 'all 0.2s ease-in-out',
21694
+ '&:hover': {
21695
+ backgroundColor: index === selectedIndex ? 'var(--theme-primary)' : 'var(--theme-border-emphasis)'
21696
+ }
21697
+ }
21698
+ }, index))
21699
+ }), renderZoomModal()]
21700
+ });
21701
+ }
21702
+ // Render grid variant
21703
+ if (variant === 'grid') {
21704
+ return jsxs(Box, {
21705
+ ...restProps,
21706
+ children: [jsx(Grid, {
21707
+ container: true,
21708
+ spacing: 2,
21709
+ children: displayImages.map((image, index) => jsx(Grid, {
21710
+ item: true,
21711
+ xs: 6,
21712
+ sm: 4,
21713
+ md: 3,
21714
+ children: jsx(Box, {
21715
+ onClick: () => {
21716
+ setSelectedIndex(index);
21717
+ handleZoomOpen();
21718
+ },
21719
+ sx: {
21720
+ width: '100%',
21721
+ aspectRatio: '1',
21722
+ borderRadius: 'var(--theme-border-radius)',
21723
+ border: '1px solid var(--theme-border-main)',
21724
+ overflow: 'hidden',
21725
+ cursor: showZoom ? 'pointer' : 'default',
21726
+ transition: 'all 0.2s ease-in-out',
21727
+ '&:hover': {
21728
+ borderColor: 'var(--theme-border-emphasis)',
21729
+ boxShadow: 'var(--theme-elevation-1)'
21730
+ }
21731
+ },
21732
+ children: jsx("img", {
21733
+ src: image.url,
21734
+ alt: image.alt || `${productName} - Image ${index + 1}`,
21735
+ style: {
21736
+ width: '100%',
21737
+ height: '100%',
21738
+ objectFit: 'cover'
21739
+ }
21740
+ })
21741
+ })
21742
+ }, index))
21743
+ }), renderZoomModal()]
21744
+ });
21745
+ }
21746
+ return null;
21747
+ }
21748
+ // Create the serializable ImageGallery component using the factory
21749
+ const ImageGallery = createSerializableView({
21750
+ tagName: 'ImageGallery',
21751
+ version: '1.0.0',
21752
+ role: 'view',
21753
+ View: ImageGalleryView
21754
+ });
21755
+
21756
+ // View component
21757
+ function OptionSelectorView({
21758
+ options = [],
21759
+ selectedOption,
21760
+ onOptionSelect,
21761
+ displayMode = 'text',
21762
+ variant = 'grid',
21763
+ layout = 'wrap',
21764
+ visualSize = 'medium',
21765
+ showLabel = false,
21766
+ disabled = false,
21767
+ label = 'Select Option',
21768
+ dataSource,
21769
+ bindingOptions,
21770
+ ...restProps
21771
+ }) {
21772
+ const handleOptionClick = useCallback((optionId, available) => {
21773
+ if (!disabled && available && onOptionSelect) {
21774
+ onOptionSelect(optionId);
21775
+ }
21776
+ }, [disabled, onOptionSelect]);
21777
+ const handleDropdownChange = useCallback(event => {
21778
+ if (onOptionSelect) {
21779
+ onOptionSelect(event.target.value);
21780
+ }
21781
+ }, [onOptionSelect]);
21782
+ // Get visual size in pixels
21783
+ const getSizePixels = () => {
21784
+ if (displayMode === 'text') return 48;
21785
+ switch (visualSize) {
21786
+ case 'small':
21787
+ return 32;
21788
+ case 'large':
21789
+ return 56;
21790
+ case 'medium':
21791
+ default:
21792
+ return 44;
21793
+ }
21794
+ };
21795
+ const sizeInPx = getSizePixels();
21796
+ // Render nothing if no options
21797
+ if (!options || options.length === 0) {
21798
+ return null;
21799
+ }
21800
+ // Dropdown variant
21801
+ if (variant === 'dropdown') {
21802
+ return jsxs(FormControl, {
21803
+ fullWidth: true,
21804
+ disabled: disabled,
21805
+ ...restProps,
21806
+ sx: {
21807
+ '& .MuiOutlinedInput-root': {
21808
+ '& fieldset': {
21809
+ borderColor: 'var(--theme-border-main)'
21810
+ },
21811
+ '&:hover fieldset': {
21812
+ borderColor: 'var(--theme-border-emphasis)'
21813
+ },
21814
+ '&.Mui-focused fieldset': {
21815
+ borderColor: 'var(--theme-primary)'
21816
+ }
21817
+ },
21818
+ '& .MuiInputLabel-root': {
21819
+ color: 'var(--theme-text-secondary)',
21820
+ '&.Mui-focused': {
21821
+ color: 'var(--theme-primary)'
21822
+ }
21823
+ }
21824
+ },
21825
+ children: [jsx(InputLabel, {
21826
+ children: label
21827
+ }), jsx(Select, {
21828
+ value: selectedOption || '',
21829
+ onChange: handleDropdownChange,
21830
+ label: label,
21831
+ sx: {
21832
+ backgroundColor: 'var(--theme-surface)',
21833
+ color: 'var(--theme-text-primary)'
21834
+ },
21835
+ children: options.map(option => jsxs(MenuItem, {
21836
+ value: option.id,
21837
+ disabled: !option.available,
21838
+ sx: {
21839
+ color: option.available ? 'var(--theme-text-primary)' : 'var(--theme-text-disabled)'
21840
+ },
21841
+ children: [displayMode === 'color' && option.hexValue && jsx(Box, {
21842
+ sx: {
21843
+ width: 20,
21844
+ height: 20,
21845
+ mr: 1,
21846
+ borderRadius: '50%',
21847
+ backgroundColor: option.hexValue,
21848
+ border: '1px solid var(--theme-border-main)',
21849
+ backgroundImage: option.imageUrl ? `url(${option.imageUrl})` : undefined,
21850
+ backgroundSize: 'cover'
21851
+ }
21852
+ }), option.label, !option.available && ' (Out of stock)', option.price && option.price !== 0 && ` (+$${(option.price / 100).toFixed(2)})`]
21853
+ }, option.id))
21854
+ })]
21855
+ });
21856
+ }
21857
+ // Buttons/Grid variant with visual modes
21858
+ const getLayoutStyles = () => {
21859
+ if (variant === 'grid') {
21860
+ const minWidth = displayMode === 'text' ? 60 : sizeInPx + 16;
21861
+ return {
21862
+ display: 'grid',
21863
+ gridTemplateColumns: `repeat(auto-fill, minmax(${minWidth}px, 1fr))`,
21864
+ gap: displayMode === 'text' ? 1 : 2
21865
+ };
21866
+ }
21867
+ return {
21868
+ display: 'flex',
21869
+ flexDirection: layout === 'vertical' ? 'column' : 'row',
21870
+ flexWrap: layout === 'wrap' ? 'wrap' : 'nowrap',
21871
+ gap: 1
21872
+ };
21873
+ };
21874
+ return jsxs(Box, {
21875
+ ...restProps,
21876
+ children: [label && jsx(Box, {
21877
+ component: "label",
21878
+ sx: {
21879
+ display: 'block',
21880
+ mb: 1,
21881
+ fontSize: '0.875rem',
21882
+ fontWeight: 500,
21883
+ color: 'var(--theme-text-primary)'
21884
+ },
21885
+ children: label
21886
+ }), jsx(Box, {
21887
+ sx: getLayoutStyles(),
21888
+ children: options.map(option => {
21889
+ const isSelected = selectedOption === option.id;
21890
+ const isAvailable = option.available;
21891
+ // Text mode - render as buttons
21892
+ if (displayMode === 'text') {
21893
+ const button = jsx(Button$1, {
21894
+ onClick: () => handleOptionClick(option.id, isAvailable),
21895
+ disabled: disabled || !isAvailable,
21896
+ variant: isSelected ? 'contained' : 'outlined',
21897
+ sx: {
21898
+ minWidth: variant === 'grid' ? '60px' : '80px',
21899
+ height: `${sizeInPx}px`,
21900
+ borderRadius: 'var(--theme-border-radius-small)',
21901
+ textTransform: 'uppercase',
21902
+ fontWeight: 600,
21903
+ fontSize: '0.875rem',
21904
+ backgroundColor: isSelected ? 'var(--theme-primary)' : 'var(--theme-surface)',
21905
+ color: isSelected ? 'var(--theme-text-on-primary)' : 'var(--theme-text-primary)',
21906
+ borderColor: isSelected ? 'var(--theme-primary)' : 'var(--theme-border-main)',
21907
+ borderWidth: '2px',
21908
+ borderStyle: 'solid',
21909
+ '&.Mui-disabled': {
21910
+ backgroundColor: 'var(--theme-surface-variant)',
21911
+ color: 'var(--theme-text-disabled)',
21912
+ borderColor: 'var(--theme-border-light)',
21913
+ opacity: 0.5,
21914
+ textDecoration: 'line-through'
21915
+ },
21916
+ '&:hover:not(.Mui-disabled)': {
21917
+ backgroundColor: !isSelected ? 'var(--theme-surface-variant)' : undefined,
21918
+ borderColor: !isSelected ? 'var(--theme-border-emphasis)' : undefined,
21919
+ boxShadow: 'var(--theme-elevation-1)'
21920
+ },
21921
+ transition: 'all 0.2s ease-in-out'
21922
+ },
21923
+ children: option.label
21924
+ }, option.id);
21925
+ return !isAvailable ? jsx(Tooltip, {
21926
+ title: "Not available",
21927
+ arrow: true,
21928
+ sx: {
21929
+ '& .MuiTooltip-tooltip': {
21930
+ backgroundColor: 'var(--theme-surface)',
21931
+ color: 'var(--theme-text-primary)',
21932
+ border: '1px solid var(--theme-border-main)',
21933
+ boxShadow: 'var(--theme-elevation-2)'
21934
+ },
21935
+ '& .MuiTooltip-arrow': {
21936
+ color: 'var(--theme-surface)'
21937
+ }
21938
+ },
21939
+ children: jsx("span", {
21940
+ children: button
21941
+ })
21942
+ }, option.id) : button;
21943
+ }
21944
+ // Color/Image mode - render as visual swatches
21945
+ const swatchContent = jsxs(Box, {
21946
+ onClick: () => handleOptionClick(option.id, isAvailable),
21947
+ sx: {
21948
+ display: 'flex',
21949
+ flexDirection: 'column',
21950
+ alignItems: 'center',
21951
+ gap: 0.5,
21952
+ cursor: disabled || !isAvailable ? 'not-allowed' : 'pointer',
21953
+ opacity: disabled || !isAvailable ? 0.5 : 1
21954
+ },
21955
+ children: [jsx(Box, {
21956
+ sx: {
21957
+ position: 'relative',
21958
+ width: sizeInPx,
21959
+ height: sizeInPx,
21960
+ borderRadius: displayMode === 'color' ? '50%' : 'var(--theme-border-radius-small)',
21961
+ backgroundColor: option.hexValue || 'var(--theme-surface-variant)',
21962
+ backgroundImage: option.imageUrl ? `url(${option.imageUrl})` : undefined,
21963
+ backgroundSize: 'cover',
21964
+ backgroundPosition: 'center',
21965
+ border: '2px solid',
21966
+ borderColor: isSelected ? 'var(--theme-primary)' : 'var(--theme-border-main)',
21967
+ boxShadow: isSelected ? 'var(--theme-elevation-2)' : 'none',
21968
+ transition: 'all 0.2s ease-in-out',
21969
+ ...(isAvailable && !disabled && !isSelected && {
21970
+ '&:hover': {
21971
+ borderColor: 'var(--theme-border-emphasis)',
21972
+ boxShadow: 'var(--theme-elevation-1)',
21973
+ transform: 'scale(1.05)'
21974
+ }
21975
+ }),
21976
+ ...(!isAvailable && {
21977
+ '&::after': {
21978
+ content: '""',
21979
+ position: 'absolute',
21980
+ top: '50%',
21981
+ left: '10%',
21982
+ right: '10%',
21983
+ height: '2px',
21984
+ backgroundColor: 'var(--theme-border-emphasis)',
21985
+ transform: 'translateY(-50%) rotate(-45deg)'
21986
+ }
21987
+ })
21988
+ },
21989
+ children: isSelected && jsx(Box, {
21990
+ sx: {
21991
+ position: 'absolute',
21992
+ top: '50%',
21993
+ left: '50%',
21994
+ transform: 'translate(-50%, -50%)',
21995
+ display: 'flex',
21996
+ alignItems: 'center',
21997
+ justifyContent: 'center',
21998
+ width: '100%',
21999
+ height: '100%',
22000
+ borderRadius: 'inherit',
22001
+ backgroundColor: 'rgba(0, 0, 0, 0.3)'
22002
+ },
22003
+ children: jsx(Check, {
22004
+ sx: {
22005
+ color: 'white',
22006
+ fontSize: sizeInPx * 0.5,
22007
+ filter: 'drop-shadow(0 1px 2px rgba(0,0,0,0.5))'
22008
+ }
22009
+ })
22010
+ })
22011
+ }), showLabel && jsx(Box, {
22012
+ sx: {
22013
+ fontSize: '0.75rem',
22014
+ color: 'var(--theme-text-secondary)',
22015
+ textAlign: 'center',
22016
+ maxWidth: sizeInPx + 16,
22017
+ overflow: 'hidden',
22018
+ textOverflow: 'ellipsis',
22019
+ whiteSpace: 'nowrap'
22020
+ },
22021
+ children: option.label
22022
+ })]
22023
+ }, option.id);
22024
+ return jsx(Tooltip, {
22025
+ title: !isAvailable ? 'Not available' : option.label,
22026
+ arrow: true,
22027
+ sx: {
22028
+ '& .MuiTooltip-tooltip': {
22029
+ backgroundColor: 'var(--theme-surface)',
22030
+ color: 'var(--theme-text-primary)',
22031
+ border: '1px solid var(--theme-border-main)',
22032
+ boxShadow: 'var(--theme-elevation-2)'
22033
+ },
22034
+ '& .MuiTooltip-arrow': {
22035
+ color: 'var(--theme-surface)'
22036
+ }
22037
+ },
22038
+ children: swatchContent
22039
+ }, option.id);
22040
+ })
22041
+ })]
22042
+ });
22043
+ }
22044
+ // Create the serializable component
22045
+ const OptionSelector = createSerializableView({
22046
+ tagName: 'OptionSelector',
22047
+ version: '1.0.0',
22048
+ role: 'view',
22049
+ View: OptionSelectorView
22050
+ });
22051
+
22052
+ // Default render function based on component type
22053
+ const getDefaultRenderItem = (renderComponent = 'ProductCard', itemProps = {}) => {
22054
+ return (item, index) => {
22055
+ const key = item?.id || item?.key || index;
22056
+ switch (renderComponent) {
22057
+ case 'ProductCard':
22058
+ return jsx(ProductCard, {
22059
+ product: item,
22060
+ ...itemProps
22061
+ }, key);
22062
+ case 'FeatureCard':
22063
+ return jsx(FeatureCard, {
22064
+ feature: item,
22065
+ ...itemProps
22066
+ }, key);
22067
+ case 'Custom':
22068
+ default:
22069
+ // For custom components, assume the item contains the component data
22070
+ return jsx("div", {
22071
+ children: JSON.stringify(item)
22072
+ }, key);
22073
+ }
22074
+ };
22075
+ };
22076
+ // View component - handles the actual rendering
22077
+ function CardListGridView({
22078
+ items = [],
22079
+ renderItem,
22080
+ renderComponent = 'ProductCard',
22081
+ itemProps = {},
22082
+ columns = 2,
22083
+ spacing = 'large',
22084
+ equalHeight = true,
22085
+ ...restProps
22086
+ }) {
22087
+ const {
22088
+ styleProps,
22089
+ htmlProps,
22090
+ restProps: otherProps
22091
+ } = useBaseProps(restProps);
22092
+ // Return null if no items and no render function
22093
+ if (!items.length && !renderItem) {
22094
+ return null;
22095
+ }
22096
+ // Use provided renderItem or create default based on renderComponent
22097
+ const actualRenderItem = renderItem || getDefaultRenderItem(renderComponent, itemProps);
22098
+ return jsx(GridLayout, {
22099
+ columns: columns,
22100
+ spacing: spacing,
22101
+ equalHeight: equalHeight,
22102
+ ...htmlProps,
22103
+ ...styleProps,
22104
+ ...otherProps,
22105
+ children: items.map((item, index) => actualRenderItem(item, index))
22106
+ });
22107
+ }
22108
+ // Main component with data binding support
22109
+ function CardListGrid(props) {
22110
+ const {
22111
+ dataSource,
22112
+ bindingOptions,
22113
+ ...restProps
22114
+ } = props;
22115
+ // Always call hooks unconditionally
22116
+ const result = useDataBinding(dataSource || '', restProps);
22117
+ // If no dataSource, use traditional props
22118
+ if (!dataSource) {
22119
+ return jsx(CardListGridView, {
22120
+ ...restProps
22121
+ });
22122
+ }
22123
+ // Use data binding result
22124
+ const {
22125
+ loading,
22126
+ error,
22127
+ ...cardListGridProps
22128
+ } = result;
22129
+ // Show loading state
22130
+ if (loading) {
22131
+ return jsx(GridLayout, {
22132
+ columns: restProps.columns || 2,
22133
+ spacing: restProps.spacing || 'large',
22134
+ style: {
22135
+ textAlign: 'center',
22136
+ padding: '2rem'
22137
+ },
22138
+ children: jsx("div", {
22139
+ children: "Loading..."
22140
+ })
22141
+ });
22142
+ }
22143
+ if (error) {
22144
+ console.error('Error loading card list grid:', error);
22145
+ {
22146
+ return jsx(GridLayout, {
22147
+ columns: restProps.columns || 2,
22148
+ spacing: restProps.spacing || 'large',
22149
+ style: {
22150
+ textAlign: 'center',
21517
22151
  padding: '2rem'
21518
22152
  },
21519
22153
  children: jsxs("div", {
@@ -22340,36 +22974,31 @@ function DialogContentText({
22340
22974
  });
22341
22975
  }
22342
22976
 
22343
- const FormField = /*#__PURE__*/React.forwardRef((props, ref) => {
22344
- const {
22345
- gridProps,
22346
- styleProps,
22347
- htmlProps,
22348
- restProps
22349
- } = useBaseProps(props);
22350
- const {
22351
- label,
22352
- value,
22353
- onChange,
22354
- onChangeRaw,
22355
- type = 'text',
22356
- helperText,
22357
- required = false,
22358
- readOnly = false,
22359
- disabled = false,
22360
- disabledColor,
22361
- fullWidth = true,
22362
- multiline = false,
22363
- rows,
22364
- placeholder,
22365
- startAdornment,
22366
- endAdornment,
22367
- inputProps
22368
- } = restProps;
22369
- // Generate a unique ID for the input field
22977
+ /**
22978
+ * FormFieldView - Pure view component that renders the input field
22979
+ */
22980
+ function FormFieldView({
22981
+ label,
22982
+ value,
22983
+ onChange,
22984
+ onChangeRaw,
22985
+ type = 'text',
22986
+ helperText,
22987
+ required = false,
22988
+ readOnly = false,
22989
+ disabled = false,
22990
+ disabledColor,
22991
+ fullWidth = true,
22992
+ multiline = false,
22993
+ rows,
22994
+ placeholder,
22995
+ startAdornment,
22996
+ endAdornment,
22997
+ inputProps,
22998
+ ...restProps
22999
+ }) {
22370
23000
  const fieldId = React.useId();
22371
23001
  const handleChange = e => {
22372
- // If onChangeRaw is provided, use it instead
22373
23002
  if (onChangeRaw) {
22374
23003
  onChangeRaw(e);
22375
23004
  return;
@@ -22393,8 +23022,7 @@ const FormField = /*#__PURE__*/React.forwardRef((props, ref) => {
22393
23022
  '& input.Mui-disabled': disabledColor ? {
22394
23023
  color: disabledColor,
22395
23024
  WebkitTextFillColor: disabledColor
22396
- } : undefined,
22397
- ...styleProps.sx
23025
+ } : undefined
22398
23026
  };
22399
23027
  const labelStyles = {
22400
23028
  left: -12,
@@ -22405,18 +23033,8 @@ const FormField = /*#__PURE__*/React.forwardRef((props, ref) => {
22405
23033
  color: 'var(--theme-secondary)'
22406
23034
  };
22407
23035
  return jsxs(FormControl, {
22408
- ref: ref,
22409
23036
  fullWidth: fullWidth,
22410
- ...htmlProps,
22411
- ...styleProps,
22412
- ...(gridProps && {
22413
- 'data-grid-span': gridProps.span,
22414
- 'data-grid-xs': gridProps.xs,
22415
- 'data-grid-sm': gridProps.sm,
22416
- 'data-grid-md': gridProps.md,
22417
- 'data-grid-lg': gridProps.lg,
22418
- 'data-grid-xl': gridProps.xl
22419
- }),
23037
+ ...restProps,
22420
23038
  children: [jsx(InputLabel, {
22421
23039
  htmlFor: fieldId,
22422
23040
  sx: labelStyles,
@@ -22448,32 +23066,33 @@ const FormField = /*#__PURE__*/React.forwardRef((props, ref) => {
22448
23066
  children: helperText
22449
23067
  })]
22450
23068
  });
22451
- });
22452
- FormField.displayName = 'FormField';
22453
- // Mark as QwickApp component
22454
- Object.assign(FormField, {
22455
- [QWICKAPP_COMPONENT]: true
23069
+ }
23070
+ /**
23071
+ * Create FormField component using the factory pattern
23072
+ */
23073
+ const FormField = createSerializableView({
23074
+ tagName: 'FormField',
23075
+ version: '1.0.0',
23076
+ role: 'input',
23077
+ View: FormFieldView
22456
23078
  });
22457
23079
 
22458
- const FormSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
22459
- const {
22460
- gridProps,
22461
- styleProps,
22462
- htmlProps,
22463
- restProps
22464
- } = useBaseProps(props);
22465
- const {
22466
- label,
22467
- value,
22468
- onChange,
22469
- options,
22470
- helperText,
22471
- required = false,
22472
- disabled = false,
22473
- fullWidth = true,
22474
- size = 'small',
22475
- placeholder
22476
- } = restProps;
23080
+ /**
23081
+ * FormSelectView - Pure view component that renders the select field
23082
+ */
23083
+ function FormSelectView({
23084
+ label,
23085
+ value,
23086
+ onChange,
23087
+ options,
23088
+ helperText,
23089
+ required = false,
23090
+ disabled = false,
23091
+ fullWidth = true,
23092
+ size = 'small',
23093
+ placeholder,
23094
+ ...restProps
23095
+ }) {
22477
23096
  const handleChange = e => {
22478
23097
  onChange(e.target.value);
22479
23098
  };
@@ -22487,8 +23106,7 @@ const FormSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
22487
23106
  backgroundColor: 'var(--theme-surface-variant)',
22488
23107
  borderColor: 'var(--theme-surface)',
22489
23108
  color: 'var(--theme-text-primary)',
22490
- borderRadius: 1,
22491
- ...styleProps.sx
23109
+ borderRadius: 1
22492
23110
  };
22493
23111
  const labelStyles = {
22494
23112
  left: -12,
@@ -22499,19 +23117,9 @@ const FormSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
22499
23117
  color: 'var(--theme-secondary)'
22500
23118
  };
22501
23119
  return jsxs(FormControl, {
22502
- ref: ref,
22503
23120
  fullWidth: fullWidth,
22504
23121
  size: size,
22505
- ...htmlProps,
22506
- ...styleProps,
22507
- ...(gridProps && {
22508
- 'data-grid-span': gridProps.span,
22509
- 'data-grid-xs': gridProps.xs,
22510
- 'data-grid-sm': gridProps.sm,
22511
- 'data-grid-md': gridProps.md,
22512
- 'data-grid-lg': gridProps.lg,
22513
- 'data-grid-xl': gridProps.xl
22514
- }),
23122
+ ...restProps,
22515
23123
  children: [label && jsx(InputLabel, {
22516
23124
  sx: labelStyles,
22517
23125
  shrink: true,
@@ -22536,28 +23144,29 @@ const FormSelect = /*#__PURE__*/React.forwardRef((props, ref) => {
22536
23144
  children: helperText
22537
23145
  })]
22538
23146
  });
22539
- });
22540
- FormSelect.displayName = 'FormSelect';
22541
- // Mark as QwickApp component
22542
- Object.assign(FormSelect, {
22543
- [QWICKAPP_COMPONENT]: true
23147
+ }
23148
+ /**
23149
+ * Create FormSelect component using the factory pattern
23150
+ */
23151
+ const FormSelect = createSerializableView({
23152
+ tagName: 'FormSelect',
23153
+ version: '1.0.0',
23154
+ role: 'input',
23155
+ View: FormSelectView
22544
23156
  });
22545
23157
 
22546
- const FormCheckbox = /*#__PURE__*/React.forwardRef((props, ref) => {
22547
- const {
22548
- gridProps,
22549
- styleProps,
22550
- htmlProps,
22551
- restProps
22552
- } = useBaseProps(props);
22553
- const {
22554
- label,
22555
- checked,
22556
- onChange,
22557
- helperText,
22558
- required = false,
22559
- disabled = false
22560
- } = restProps;
23158
+ /**
23159
+ * FormCheckboxView - Pure view component that renders the checkbox
23160
+ */
23161
+ function FormCheckboxView({
23162
+ label,
23163
+ checked,
23164
+ onChange,
23165
+ helperText,
23166
+ required = false,
23167
+ disabled = false,
23168
+ ...restProps
23169
+ }) {
22561
23170
  const handleChange = e => {
22562
23171
  onChange(e.target.checked);
22563
23172
  };
@@ -22577,25 +23186,14 @@ const FormCheckbox = /*#__PURE__*/React.forwardRef((props, ref) => {
22577
23186
  },
22578
23187
  '& .MuiFormControlLabel-label.Mui-disabled': {
22579
23188
  color: 'var(--theme-text-disabled)'
22580
- },
22581
- ...styleProps.sx
23189
+ }
22582
23190
  };
22583
23191
  const helperTextStyles = {
22584
23192
  color: 'var(--theme-secondary)',
22585
- marginLeft: '32px' // Align with checkbox + label
23193
+ marginLeft: '32px'
22586
23194
  };
22587
23195
  return jsxs(FormControl, {
22588
- ref: ref,
22589
- ...htmlProps,
22590
- ...styleProps,
22591
- ...(gridProps && {
22592
- 'data-grid-span': gridProps.span,
22593
- 'data-grid-xs': gridProps.xs,
22594
- 'data-grid-sm': gridProps.sm,
22595
- 'data-grid-md': gridProps.md,
22596
- 'data-grid-lg': gridProps.lg,
22597
- 'data-grid-xl': gridProps.xl
22598
- }),
23196
+ ...restProps,
22599
23197
  children: [jsx(FormControlLabel, {
22600
23198
  control: jsx(Checkbox, {
22601
23199
  checked: checked,
@@ -22611,30 +23209,31 @@ const FormCheckbox = /*#__PURE__*/React.forwardRef((props, ref) => {
22611
23209
  children: helperText
22612
23210
  })]
22613
23211
  });
22614
- });
22615
- FormCheckbox.displayName = 'FormCheckbox';
22616
- // Mark as QwickApp component
22617
- Object.assign(FormCheckbox, {
22618
- [QWICKAPP_COMPONENT]: true
23212
+ }
23213
+ /**
23214
+ * Create FormCheckbox component using the factory pattern
23215
+ */
23216
+ const FormCheckbox = createSerializableView({
23217
+ tagName: 'FormCheckbox',
23218
+ version: '1.0.0',
23219
+ role: 'input',
23220
+ View: FormCheckboxView
22619
23221
  });
22620
23222
 
22621
- const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22622
- const {
22623
- gridProps,
22624
- styleProps,
22625
- htmlProps,
22626
- restProps
22627
- } = useBaseProps(props);
22628
- const {
22629
- provider,
22630
- siteKey,
22631
- onVerify,
22632
- onExpire,
22633
- onError,
22634
- theme = 'light',
22635
- size = 'normal',
22636
- action = 'submit'
22637
- } = restProps;
23223
+ /**
23224
+ * CaptchaView - Pure view component that renders the CAPTCHA widget
23225
+ */
23226
+ function CaptchaView({
23227
+ provider,
23228
+ siteKey,
23229
+ onVerify,
23230
+ onExpire,
23231
+ onError,
23232
+ theme = 'light',
23233
+ size = 'normal',
23234
+ action = 'submit',
23235
+ ...restProps
23236
+ }) {
22638
23237
  const containerRef = useRef(null);
22639
23238
  const widgetIdRef = useRef(null);
22640
23239
  const [isLoaded, setIsLoaded] = useState(false);
@@ -22707,7 +23306,7 @@ const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22707
23306
  try {
22708
23307
  switch (provider) {
22709
23308
  case 'recaptcha-v2':
22710
- if (window.grecaptcha && window.grecaptcha.render) {
23309
+ if (window.grecaptcha?.render) {
22711
23310
  widgetIdRef.current = window.grecaptcha.render(containerRef.current, {
22712
23311
  sitekey: siteKey,
22713
23312
  callback: onVerify,
@@ -22724,7 +23323,7 @@ const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22724
23323
  break;
22725
23324
  case 'recaptcha-v3':
22726
23325
  // reCAPTCHA v3 is invisible and executes programmatically
22727
- if (window.grecaptcha && window.grecaptcha.execute) {
23326
+ if (window.grecaptcha?.execute) {
22728
23327
  window.grecaptcha.execute(siteKey, {
22729
23328
  action
22730
23329
  }).then(token => {
@@ -22736,7 +23335,7 @@ const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22736
23335
  }
22737
23336
  break;
22738
23337
  case 'hcaptcha':
22739
- if (window.hcaptcha && window.hcaptcha.render) {
23338
+ if (window.hcaptcha?.render) {
22740
23339
  widgetIdRef.current = window.hcaptcha.render(containerRef.current, {
22741
23340
  sitekey: siteKey,
22742
23341
  callback: onVerify,
@@ -22752,7 +23351,7 @@ const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22752
23351
  }
22753
23352
  break;
22754
23353
  case 'turnstile':
22755
- if (window.turnstile && window.turnstile.render) {
23354
+ if (window.turnstile?.render) {
22756
23355
  widgetIdRef.current = window.turnstile.render(containerRef.current, {
22757
23356
  sitekey: siteKey,
22758
23357
  callback: onVerify,
@@ -22803,20 +23402,10 @@ const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22803
23402
  return null;
22804
23403
  }
22805
23404
  return jsxs(Box, {
22806
- ref: ref,
22807
- ...htmlProps,
23405
+ ...restProps,
22808
23406
  sx: {
22809
- my: 2,
22810
- ...styleProps.sx
23407
+ my: 2
22811
23408
  },
22812
- ...(gridProps && {
22813
- 'data-grid-span': gridProps.span,
22814
- 'data-grid-xs': gridProps.xs,
22815
- 'data-grid-sm': gridProps.sm,
22816
- 'data-grid-md': gridProps.md,
22817
- 'data-grid-lg': gridProps.lg,
22818
- 'data-grid-xl': gridProps.xl
22819
- }),
22820
23409
  children: [error && jsx(Alert, {
22821
23410
  severity: "error",
22822
23411
  sx: {
@@ -22827,11 +23416,15 @@ const Captcha = /*#__PURE__*/React.forwardRef((props, ref) => {
22827
23416
  ref: containerRef
22828
23417
  })]
22829
23418
  });
22830
- });
22831
- Captcha.displayName = 'Captcha';
22832
- // Mark as QwickApp component
22833
- Object.assign(Captcha, {
22834
- [QWICKAPP_COMPONENT]: true
23419
+ }
23420
+ /**
23421
+ * Create Captcha component using the factory pattern
23422
+ */
23423
+ const Captcha = createSerializableView({
23424
+ tagName: 'Captcha',
23425
+ version: '1.0.0',
23426
+ role: 'input',
23427
+ View: CaptchaView
22835
23428
  });
22836
23429
 
22837
23430
  /**
@@ -30338,97 +30931,331 @@ __decorate([Field(), Editor({
30338
30931
  FeatureGridModel = __decorate([Schema('FeatureGrid', '1.0.0')], FeatureGridModel);
30339
30932
 
30340
30933
  /**
30341
- * FooterItem Schema - Defines data structure for footer navigation items
30934
+ * FooterItem Schema - Defines data structure for footer navigation items
30935
+ *
30936
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
30937
+ */
30938
+ let FooterItemModel = class FooterItemModel extends Model {};
30939
+ __decorate([Field(), Editor({
30940
+ field_type: FieldType.TEXT,
30941
+ label: 'ID',
30942
+ description: 'Unique identifier for the footer item',
30943
+ placeholder: 'footer-item-id'
30944
+ }), IsString(), IsNotEmpty(), __metadata("design:type", String)], FooterItemModel.prototype, "id", void 0);
30945
+ __decorate([Field(), Editor({
30946
+ field_type: FieldType.TEXT,
30947
+ label: 'Label',
30948
+ description: 'Display text for the footer item',
30949
+ placeholder: 'Navigation label'
30950
+ }), IsString(), __metadata("design:type", String)], FooterItemModel.prototype, "label", void 0);
30951
+ __decorate([Field(), Editor({
30952
+ field_type: FieldType.URL,
30953
+ label: 'URL',
30954
+ description: 'Optional URL for links',
30955
+ placeholder: 'https://example.com'
30956
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FooterItemModel.prototype, "href", void 0);
30957
+ __decorate([Field({
30958
+ defaultValue: false
30959
+ }), Editor({
30960
+ field_type: FieldType.BOOLEAN,
30961
+ label: 'External Link',
30962
+ description: 'Whether to open links in new tab'
30963
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FooterItemModel.prototype, "external", void 0);
30964
+ FooterItemModel = __decorate([Schema('FooterItem', '1.0.0')], FooterItemModel);
30965
+
30966
+ /**
30967
+ * Schema for FormBlock component - Reusable form layout container
30968
+ *
30969
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
30970
+ */
30971
+ let FormBlockModel = class FormBlockModel extends ContainerSchema {};
30972
+ __decorate([Field(), Editor({
30973
+ field_type: FieldType.TEXT,
30974
+ label: 'Title',
30975
+ description: 'Title for the default header (ignored if custom header is provided)',
30976
+ placeholder: 'Enter form title...'
30977
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "title", void 0);
30978
+ __decorate([Field(), Editor({
30979
+ field_type: FieldType.TEXTAREA,
30980
+ label: 'Description',
30981
+ description: 'Description/subtitle for the default header (ignored if custom header is provided)',
30982
+ placeholder: 'Enter form description...'
30983
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "description", void 0);
30984
+ __decorate([Field(), Editor({
30985
+ field_type: FieldType.TEXT,
30986
+ label: 'Cover Image URL',
30987
+ description: 'Cover image URL for the default header (ignored if custom header is provided)',
30988
+ placeholder: 'https://example.com/image.jpg'
30989
+ }), IsOptional(), IsString(), __metadata("design:type", Object)], FormBlockModel.prototype, "coverImage", void 0);
30990
+ __decorate([Field(), Editor({
30991
+ field_type: FieldType.TEXT,
30992
+ label: 'Status Type',
30993
+ description: 'Status type for message display (info, success, warning, error)',
30994
+ placeholder: 'info'
30995
+ }), IsOptional(), IsIn(['info', 'success', 'warning', 'error']), __metadata("design:type", String)], FormBlockModel.prototype, "status", void 0);
30996
+ __decorate([Field(), Editor({
30997
+ field_type: FieldType.TEXTAREA,
30998
+ label: 'Status Message',
30999
+ description: 'Status message to display',
31000
+ placeholder: 'Enter status message...'
31001
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "message", void 0);
31002
+ __decorate([Field({
31003
+ defaultValue: 'sm'
31004
+ }), Editor({
31005
+ field_type: FieldType.TEXT,
31006
+ label: 'Maximum Width',
31007
+ description: 'Maximum width of the form container (xs, sm, md)',
31008
+ placeholder: 'sm'
31009
+ }), IsOptional(), IsIn(['xs', 'sm', 'md']), __metadata("design:type", String)], FormBlockModel.prototype, "maxWidth", void 0);
31010
+ __decorate([Field({
31011
+ defaultValue: 'default'
31012
+ }), Editor({
31013
+ field_type: FieldType.TEXT,
31014
+ label: 'Background Style',
31015
+ description: 'Background style variant (default, gradient, image)',
31016
+ placeholder: 'default'
31017
+ }), IsOptional(), IsIn(['default', 'gradient', 'image']), __metadata("design:type", String)], FormBlockModel.prototype, "background", void 0);
31018
+ __decorate([Field(), Editor({
31019
+ field_type: FieldType.TEXT,
31020
+ label: 'Background Image URL',
31021
+ description: 'Background image URL (when background="image")',
31022
+ placeholder: 'https://example.com/background.jpg'
31023
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "backgroundImage", void 0);
31024
+ FormBlockModel = __decorate([Schema('FormBlock', '1.0.0')], FormBlockModel);
31025
+
31026
+ /**
31027
+ * Schema for FormSelect component - Themed dropdown select input
31028
+ *
31029
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
31030
+ */
31031
+ let FormSelectModel = class FormSelectModel extends ViewSchema$1 {};
31032
+ __decorate([Field(), Editor({
31033
+ field_type: FieldType.TEXT,
31034
+ label: 'Label',
31035
+ description: 'Label text for the select field',
31036
+ placeholder: 'Enter label...'
31037
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormSelectModel.prototype, "label", void 0);
31038
+ __decorate([Field(), Editor({
31039
+ field_type: FieldType.TEXT,
31040
+ label: 'Value',
31041
+ description: 'Current selected value',
31042
+ placeholder: ''
31043
+ }), IsString(), __metadata("design:type", Object)], FormSelectModel.prototype, "value", void 0);
31044
+ __decorate([Field(), Editor({
31045
+ field_type: FieldType.TEXTAREA,
31046
+ label: 'Options',
31047
+ description: 'Select options as JSON array: [{"value": "1", "label": "Option 1"}]',
31048
+ placeholder: '[{"value": "1", "label": "Option 1"}]'
31049
+ }), IsString(), __metadata("design:type", String)], FormSelectModel.prototype, "options", void 0);
31050
+ __decorate([Field(), Editor({
31051
+ field_type: FieldType.TEXT,
31052
+ label: 'Helper Text',
31053
+ description: 'Helper text displayed below the select',
31054
+ placeholder: 'Enter helper text...'
31055
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormSelectModel.prototype, "helperText", void 0);
31056
+ __decorate([Field({
31057
+ defaultValue: false
31058
+ }), Editor({
31059
+ field_type: FieldType.BOOLEAN,
31060
+ label: 'Required',
31061
+ description: 'Mark field as required'
31062
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormSelectModel.prototype, "required", void 0);
31063
+ __decorate([Field({
31064
+ defaultValue: false
31065
+ }), Editor({
31066
+ field_type: FieldType.BOOLEAN,
31067
+ label: 'Disabled',
31068
+ description: 'Disable the select field'
31069
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormSelectModel.prototype, "disabled", void 0);
31070
+ __decorate([Field({
31071
+ defaultValue: true
31072
+ }), Editor({
31073
+ field_type: FieldType.BOOLEAN,
31074
+ label: 'Full Width',
31075
+ description: 'Make select take full width of container'
31076
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormSelectModel.prototype, "fullWidth", void 0);
31077
+ __decorate([Field({
31078
+ defaultValue: 'small'
31079
+ }), Editor({
31080
+ field_type: FieldType.SELECT,
31081
+ label: 'Size',
31082
+ description: 'Size variant of the select field'
31083
+ }), IsOptional(), IsIn(['small', 'medium']), __metadata("design:type", String)], FormSelectModel.prototype, "size", void 0);
31084
+ __decorate([Field(), Editor({
31085
+ field_type: FieldType.TEXT,
31086
+ label: 'Placeholder',
31087
+ description: 'Placeholder text when no value is selected',
31088
+ placeholder: 'Select an option...'
31089
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormSelectModel.prototype, "placeholder", void 0);
31090
+ FormSelectModel = __decorate([Schema('FormSelect', '1.0.0')], FormSelectModel);
31091
+
31092
+ /**
31093
+ * Schema for FormField component - Themed text/number input field
31094
+ *
31095
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
31096
+ */
31097
+ let FormFieldModel = class FormFieldModel extends ViewSchema$1 {};
31098
+ __decorate([Field(), Editor({
31099
+ field_type: FieldType.TEXT,
31100
+ label: 'Label',
31101
+ description: 'Label text for the input field',
31102
+ placeholder: 'Enter label...'
31103
+ }), IsString(), __metadata("design:type", String)], FormFieldModel.prototype, "label", void 0);
31104
+ __decorate([Field(), Editor({
31105
+ field_type: FieldType.TEXT,
31106
+ label: 'Value',
31107
+ description: 'Current input value',
31108
+ placeholder: ''
31109
+ }), IsString(), __metadata("design:type", Object)], FormFieldModel.prototype, "value", void 0);
31110
+ __decorate([Field({
31111
+ defaultValue: 'text'
31112
+ }), Editor({
31113
+ field_type: FieldType.SELECT,
31114
+ label: 'Input Type',
31115
+ description: 'Type of input field'
31116
+ }), IsOptional(), IsIn(['text', 'number', 'password', 'email', 'tel']), __metadata("design:type", String)], FormFieldModel.prototype, "type", void 0);
31117
+ __decorate([Field(), Editor({
31118
+ field_type: FieldType.TEXT,
31119
+ label: 'Helper Text',
31120
+ description: 'Helper text displayed below the input',
31121
+ placeholder: 'Enter helper text...'
31122
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormFieldModel.prototype, "helperText", void 0);
31123
+ __decorate([Field({
31124
+ defaultValue: false
31125
+ }), Editor({
31126
+ field_type: FieldType.BOOLEAN,
31127
+ label: 'Required',
31128
+ description: 'Mark field as required'
31129
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormFieldModel.prototype, "required", void 0);
31130
+ __decorate([Field({
31131
+ defaultValue: false
31132
+ }), Editor({
31133
+ field_type: FieldType.BOOLEAN,
31134
+ label: 'Read Only',
31135
+ description: 'Make field read-only'
31136
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormFieldModel.prototype, "readOnly", void 0);
31137
+ __decorate([Field({
31138
+ defaultValue: false
31139
+ }), Editor({
31140
+ field_type: FieldType.BOOLEAN,
31141
+ label: 'Disabled',
31142
+ description: 'Disable the input field'
31143
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormFieldModel.prototype, "disabled", void 0);
31144
+ __decorate([Field(), Editor({
31145
+ field_type: FieldType.TEXT,
31146
+ label: 'Disabled Color',
31147
+ description: 'Custom color for disabled state (CSS color value)',
31148
+ placeholder: 'var(--theme-text-disabled)'
31149
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormFieldModel.prototype, "disabledColor", void 0);
31150
+ __decorate([Field({
31151
+ defaultValue: true
31152
+ }), Editor({
31153
+ field_type: FieldType.BOOLEAN,
31154
+ label: 'Full Width',
31155
+ description: 'Make input take full width of container'
31156
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormFieldModel.prototype, "fullWidth", void 0);
31157
+ __decorate([Field({
31158
+ defaultValue: false
31159
+ }), Editor({
31160
+ field_type: FieldType.BOOLEAN,
31161
+ label: 'Multiline',
31162
+ description: 'Enable multiline textarea mode'
31163
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormFieldModel.prototype, "multiline", void 0);
31164
+ __decorate([Field(), Editor({
31165
+ field_type: FieldType.TEXT,
31166
+ label: 'Rows',
31167
+ description: 'Number of rows for multiline textarea',
31168
+ placeholder: '4'
31169
+ }), IsOptional(), IsInt(), Min(1), __metadata("design:type", Number)], FormFieldModel.prototype, "rows", void 0);
31170
+ __decorate([Field(), Editor({
31171
+ field_type: FieldType.TEXT,
31172
+ label: 'Placeholder',
31173
+ description: 'Placeholder text',
31174
+ placeholder: 'Enter text...'
31175
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormFieldModel.prototype, "placeholder", void 0);
31176
+ FormFieldModel = __decorate([Schema('FormField', '1.0.0')], FormFieldModel);
31177
+
31178
+ /**
31179
+ * Schema for FormCheckbox component - Themed checkbox input
30342
31180
  *
30343
31181
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
30344
31182
  */
30345
- let FooterItemModel = class FooterItemModel extends Model {};
30346
- __decorate([Field(), Editor({
30347
- field_type: FieldType.TEXT,
30348
- label: 'ID',
30349
- description: 'Unique identifier for the footer item',
30350
- placeholder: 'footer-item-id'
30351
- }), IsString(), IsNotEmpty(), __metadata("design:type", String)], FooterItemModel.prototype, "id", void 0);
31183
+ let FormCheckboxModel = class FormCheckboxModel extends ViewSchema$1 {};
30352
31184
  __decorate([Field(), Editor({
30353
31185
  field_type: FieldType.TEXT,
30354
31186
  label: 'Label',
30355
- description: 'Display text for the footer item',
30356
- placeholder: 'Navigation label'
30357
- }), IsString(), __metadata("design:type", String)], FooterItemModel.prototype, "label", void 0);
31187
+ description: 'Label text for the checkbox',
31188
+ placeholder: 'Enter label...'
31189
+ }), IsString(), __metadata("design:type", String)], FormCheckboxModel.prototype, "label", void 0);
31190
+ __decorate([Field({
31191
+ defaultValue: false
31192
+ }), Editor({
31193
+ field_type: FieldType.BOOLEAN,
31194
+ label: 'Checked',
31195
+ description: 'Checkbox checked state'
31196
+ }), IsBoolean(), __metadata("design:type", Boolean)], FormCheckboxModel.prototype, "checked", void 0);
30358
31197
  __decorate([Field(), Editor({
30359
- field_type: FieldType.URL,
30360
- label: 'URL',
30361
- description: 'Optional URL for links',
30362
- placeholder: 'https://example.com'
30363
- }), IsOptional(), IsString(), __metadata("design:type", String)], FooterItemModel.prototype, "href", void 0);
31198
+ field_type: FieldType.TEXT,
31199
+ label: 'Helper Text',
31200
+ description: 'Helper text displayed below the checkbox',
31201
+ placeholder: 'Enter helper text...'
31202
+ }), IsOptional(), IsString(), __metadata("design:type", String)], FormCheckboxModel.prototype, "helperText", void 0);
30364
31203
  __decorate([Field({
30365
31204
  defaultValue: false
30366
31205
  }), Editor({
30367
31206
  field_type: FieldType.BOOLEAN,
30368
- label: 'External Link',
30369
- description: 'Whether to open links in new tab'
30370
- }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FooterItemModel.prototype, "external", void 0);
30371
- FooterItemModel = __decorate([Schema('FooterItem', '1.0.0')], FooterItemModel);
31207
+ label: 'Required',
31208
+ description: 'Mark checkbox as required'
31209
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormCheckboxModel.prototype, "required", void 0);
31210
+ __decorate([Field({
31211
+ defaultValue: false
31212
+ }), Editor({
31213
+ field_type: FieldType.BOOLEAN,
31214
+ label: 'Disabled',
31215
+ description: 'Disable the checkbox'
31216
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], FormCheckboxModel.prototype, "disabled", void 0);
31217
+ FormCheckboxModel = __decorate([Schema('FormCheckbox', '1.0.0')], FormCheckboxModel);
30372
31218
 
30373
31219
  /**
30374
- * Schema for FormBlock component - Reusable form layout container
31220
+ * Schema for Captcha component - Universal CAPTCHA widget
30375
31221
  *
30376
31222
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
30377
31223
  */
30378
- let FormBlockModel = class FormBlockModel extends ContainerSchema {};
30379
- __decorate([Field(), Editor({
30380
- field_type: FieldType.TEXT,
30381
- label: 'Title',
30382
- description: 'Title for the default header (ignored if custom header is provided)',
30383
- placeholder: 'Enter form title...'
30384
- }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "title", void 0);
30385
- __decorate([Field(), Editor({
30386
- field_type: FieldType.TEXTAREA,
30387
- label: 'Description',
30388
- description: 'Description/subtitle for the default header (ignored if custom header is provided)',
30389
- placeholder: 'Enter form description...'
30390
- }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "description", void 0);
31224
+ let CaptchaModel = class CaptchaModel extends ViewSchema$1 {};
30391
31225
  __decorate([Field(), Editor({
30392
- field_type: FieldType.TEXT,
30393
- label: 'Cover Image URL',
30394
- description: 'Cover image URL for the default header (ignored if custom header is provided)',
30395
- placeholder: 'https://example.com/image.jpg'
30396
- }), IsOptional(), IsString(), __metadata("design:type", Object)], FormBlockModel.prototype, "coverImage", void 0);
31226
+ field_type: FieldType.SELECT,
31227
+ label: 'CAPTCHA Provider',
31228
+ description: 'Which CAPTCHA service to use'
31229
+ }), IsIn(['recaptcha-v2', 'recaptcha-v3', 'hcaptcha', 'turnstile']), __metadata("design:type", String)], CaptchaModel.prototype, "provider", void 0);
30397
31230
  __decorate([Field(), Editor({
30398
31231
  field_type: FieldType.TEXT,
30399
- label: 'Status Type',
30400
- description: 'Status type for message display (info, success, warning, error)',
30401
- placeholder: 'info'
30402
- }), IsOptional(), IsIn(['info', 'success', 'warning', 'error']), __metadata("design:type", String)], FormBlockModel.prototype, "status", void 0);
30403
- __decorate([Field(), Editor({
30404
- field_type: FieldType.TEXTAREA,
30405
- label: 'Status Message',
30406
- description: 'Status message to display',
30407
- placeholder: 'Enter status message...'
30408
- }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "message", void 0);
31232
+ label: 'Site Key',
31233
+ description: 'Public site key from CAPTCHA provider',
31234
+ placeholder: 'Enter site key...'
31235
+ }), IsString(), __metadata("design:type", String)], CaptchaModel.prototype, "siteKey", void 0);
30409
31236
  __decorate([Field({
30410
- defaultValue: 'sm'
31237
+ defaultValue: 'light'
30411
31238
  }), Editor({
30412
- field_type: FieldType.TEXT,
30413
- label: 'Maximum Width',
30414
- description: 'Maximum width of the form container (xs, sm, md)',
30415
- placeholder: 'sm'
30416
- }), IsOptional(), IsIn(['xs', 'sm', 'md']), __metadata("design:type", String)], FormBlockModel.prototype, "maxWidth", void 0);
31239
+ field_type: FieldType.SELECT,
31240
+ label: 'Theme',
31241
+ description: 'CAPTCHA widget theme'
31242
+ }), IsOptional(), IsIn(['light', 'dark']), __metadata("design:type", String)], CaptchaModel.prototype, "theme", void 0);
30417
31243
  __decorate([Field({
30418
- defaultValue: 'default'
31244
+ defaultValue: 'normal'
31245
+ }), Editor({
31246
+ field_type: FieldType.SELECT,
31247
+ label: 'Size',
31248
+ description: 'CAPTCHA widget size'
31249
+ }), IsOptional(), IsIn(['normal', 'compact', 'invisible']), __metadata("design:type", String)], CaptchaModel.prototype, "size", void 0);
31250
+ __decorate([Field({
31251
+ defaultValue: 'submit'
30419
31252
  }), Editor({
30420
31253
  field_type: FieldType.TEXT,
30421
- label: 'Background Style',
30422
- description: 'Background style variant (default, gradient, image)',
30423
- placeholder: 'default'
30424
- }), IsOptional(), IsIn(['default', 'gradient', 'image']), __metadata("design:type", String)], FormBlockModel.prototype, "background", void 0);
30425
- __decorate([Field(), Editor({
30426
- field_type: FieldType.TEXT,
30427
- label: 'Background Image URL',
30428
- description: 'Background image URL (when background="image")',
30429
- placeholder: 'https://example.com/background.jpg'
30430
- }), IsOptional(), IsString(), __metadata("design:type", String)], FormBlockModel.prototype, "backgroundImage", void 0);
30431
- FormBlockModel = __decorate([Schema('FormBlock', '1.0.0')], FormBlockModel);
31254
+ label: 'Action',
31255
+ description: 'reCAPTCHA v3 action name',
31256
+ placeholder: 'submit'
31257
+ }), IsOptional(), IsString(), __metadata("design:type", String)], CaptchaModel.prototype, "action", void 0);
31258
+ CaptchaModel = __decorate([Schema('Captcha', '1.0.0')], CaptchaModel);
30432
31259
 
30433
31260
  /**
30434
31261
  * FooterSection Schema - Defines data structure for footer sections
@@ -31434,6 +32261,299 @@ __decorate([Field({
31434
32261
  }), IsOptional(), IsNumber(), Min(1), Max(10), __metadata("design:type", Number)], ProductCardModel.prototype, "maxFeaturesCompact", void 0);
31435
32262
  ProductCardModel = __decorate([Schema('ProductCard', '1.0.0')], ProductCardModel);
31436
32263
 
32264
+ /**
32265
+ * Schema for ImageGallery component - Image gallery with multiple view variants
32266
+ *
32267
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
32268
+ */
32269
+ // Product image interface
32270
+ class GalleryImageModel {}
32271
+ __decorate([Field({
32272
+ dataType: DataType.STRING
32273
+ }), IsString(), __metadata("design:type", String)], GalleryImageModel.prototype, "url", void 0);
32274
+ __decorate([Field({
32275
+ dataType: DataType.STRING
32276
+ }), IsString(), __metadata("design:type", String)], GalleryImageModel.prototype, "alt", void 0);
32277
+ __decorate([Field({
32278
+ dataType: DataType.STRING
32279
+ }), IsOptional(), IsString(), __metadata("design:type", String)], GalleryImageModel.prototype, "thumbnail", void 0);
32280
+ let ImageGalleryModel = class ImageGalleryModel extends ViewSchema {};
32281
+ __decorate([Field({
32282
+ dataType: DataType.ARRAY
32283
+ }), Editor({
32284
+ field_type: FieldType.ARRAY,
32285
+ label: 'Product Images',
32286
+ description: 'Array of product images to display in the gallery'
32287
+ }), IsArray(), ValidateNested({
32288
+ each: true
32289
+ }), Type(() => GalleryImageModel), __metadata("design:type", Array)], ImageGalleryModel.prototype, "images", void 0);
32290
+ __decorate([Field({
32291
+ dataType: DataType.STRING
32292
+ }), Editor({
32293
+ field_type: FieldType.TEXT,
32294
+ label: 'Product Name',
32295
+ description: 'Product name for accessibility',
32296
+ placeholder: 'Premium Cotton T-Shirt'
32297
+ }), IsString(), __metadata("design:type", String)], ImageGalleryModel.prototype, "productName", void 0);
32298
+ __decorate([Field({
32299
+ defaultValue: 'thumbnails',
32300
+ dataType: DataType.STRING
32301
+ }), Editor({
32302
+ field_type: FieldType.SELECT,
32303
+ label: 'Gallery Variant',
32304
+ description: 'Display variant for the gallery',
32305
+ validation: {
32306
+ options: [{
32307
+ label: 'Thumbnails',
32308
+ value: 'thumbnails'
32309
+ }, {
32310
+ label: 'Carousel',
32311
+ value: 'carousel'
32312
+ }, {
32313
+ label: 'Grid',
32314
+ value: 'grid'
32315
+ }]
32316
+ }
32317
+ }), IsOptional(), IsString(), IsIn(['thumbnails', 'carousel', 'grid']), __metadata("design:type", String)], ImageGalleryModel.prototype, "variant", void 0);
32318
+ __decorate([Field({
32319
+ defaultValue: 'left',
32320
+ dataType: DataType.STRING
32321
+ }), Editor({
32322
+ field_type: FieldType.SELECT,
32323
+ label: 'Thumbnail Position',
32324
+ description: 'Position of thumbnails (only for thumbnails variant)',
32325
+ validation: {
32326
+ options: [{
32327
+ label: 'Left',
32328
+ value: 'left'
32329
+ }, {
32330
+ label: 'Bottom',
32331
+ value: 'bottom'
32332
+ }, {
32333
+ label: 'Right',
32334
+ value: 'right'
32335
+ }]
32336
+ }
32337
+ }), IsOptional(), IsString(), IsIn(['left', 'bottom', 'right']), __metadata("design:type", String)], ImageGalleryModel.prototype, "thumbnailPosition", void 0);
32338
+ __decorate([Field({
32339
+ defaultValue: '1',
32340
+ dataType: DataType.STRING
32341
+ }), Editor({
32342
+ field_type: FieldType.TEXT,
32343
+ label: 'Aspect Ratio',
32344
+ description: 'Aspect ratio for main image (e.g., "1", "4/3", "16/9")',
32345
+ placeholder: '1'
32346
+ }), IsOptional(), IsString(), __metadata("design:type", String)], ImageGalleryModel.prototype, "aspectRatio", void 0);
32347
+ __decorate([Field({
32348
+ defaultValue: true,
32349
+ dataType: DataType.BOOLEAN
32350
+ }), Editor({
32351
+ field_type: FieldType.BOOLEAN,
32352
+ label: 'Show Zoom',
32353
+ description: 'Enable zoom functionality for images'
32354
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], ImageGalleryModel.prototype, "showZoom", void 0);
32355
+ __decorate([Field({
32356
+ dataType: DataType.NUMBER
32357
+ }), Editor({
32358
+ field_type: FieldType.NUMBER,
32359
+ label: 'Max Images',
32360
+ description: 'Maximum number of images to display (leave empty for all)',
32361
+ placeholder: '8'
32362
+ }), IsOptional(), IsNumber(), __metadata("design:type", Number)], ImageGalleryModel.prototype, "maxImages", void 0);
32363
+ __decorate([Field({
32364
+ dataType: DataType.STRING
32365
+ }), Editor({
32366
+ field_type: FieldType.TEXT,
32367
+ label: 'Data Source',
32368
+ description: 'Data source for dynamic image loading',
32369
+ placeholder: 'product-images'
32370
+ }), IsOptional(), IsString(), __metadata("design:type", String)], ImageGalleryModel.prototype, "dataSource", void 0);
32371
+ __decorate([Field({
32372
+ dataType: DataType.OBJECT
32373
+ }), Editor({
32374
+ field_type: FieldType.TEXTAREA,
32375
+ label: 'Binding Options',
32376
+ description: 'Data binding configuration (JSON format)',
32377
+ placeholder: '{ "filter": {}, "sort": {} }'
32378
+ }), IsOptional(), __metadata("design:type", Object)], ImageGalleryModel.prototype, "bindingOptions", void 0);
32379
+ ImageGalleryModel = __decorate([Schema('ImageGallery', '1.0.0')], ImageGalleryModel);
32380
+
32381
+ /**
32382
+ * Schema for OptionSelector component - Universal option selection with visual modes
32383
+ *
32384
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
32385
+ */
32386
+ // Select option model
32387
+ class SelectOptionModel {}
32388
+ __decorate([Field({
32389
+ dataType: DataType.STRING
32390
+ }), IsString(), __metadata("design:type", String)], SelectOptionModel.prototype, "id", void 0);
32391
+ __decorate([Field({
32392
+ dataType: DataType.STRING
32393
+ }), IsString(), __metadata("design:type", String)], SelectOptionModel.prototype, "label", void 0);
32394
+ __decorate([Field({
32395
+ dataType: DataType.BOOLEAN
32396
+ }), IsBoolean(), __metadata("design:type", Boolean)], SelectOptionModel.prototype, "available", void 0);
32397
+ __decorate([Field({
32398
+ dataType: DataType.NUMBER
32399
+ }), IsOptional(), IsNumber(), __metadata("design:type", Number)], SelectOptionModel.prototype, "price", void 0);
32400
+ __decorate([Field({
32401
+ dataType: DataType.STRING
32402
+ }), Editor({
32403
+ field_type: FieldType.TEXT,
32404
+ label: 'Hex Color Value',
32405
+ description: 'Hex color code for color swatches (e.g., #FF0000)',
32406
+ placeholder: '#FF0000'
32407
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SelectOptionModel.prototype, "hexValue", void 0);
32408
+ __decorate([Field({
32409
+ dataType: DataType.STRING
32410
+ }), Editor({
32411
+ field_type: FieldType.TEXT,
32412
+ label: 'Image URL',
32413
+ description: 'Image URL for image/pattern display mode',
32414
+ placeholder: '/patterns/stripes.jpg'
32415
+ }), IsOptional(), IsString(), __metadata("design:type", String)], SelectOptionModel.prototype, "imageUrl", void 0);
32416
+ let OptionSelectorModel = class OptionSelectorModel extends ViewSchema {};
32417
+ __decorate([Field({
32418
+ dataType: DataType.ARRAY
32419
+ }), Editor({
32420
+ field_type: FieldType.ARRAY,
32421
+ label: 'Available Options',
32422
+ description: 'Array of options to display'
32423
+ }), IsArray(), ValidateNested({
32424
+ each: true
32425
+ }), Type(() => SelectOptionModel), __metadata("design:type", Array)], OptionSelectorModel.prototype, "options", void 0);
32426
+ __decorate([Field({
32427
+ dataType: DataType.STRING
32428
+ }), Editor({
32429
+ field_type: FieldType.TEXT,
32430
+ label: 'Selected Option',
32431
+ description: 'Currently selected option ID',
32432
+ placeholder: 'm'
32433
+ }), IsOptional(), IsString(), __metadata("design:type", String)], OptionSelectorModel.prototype, "selectedOption", void 0);
32434
+ __decorate([Field({
32435
+ defaultValue: 'text',
32436
+ dataType: DataType.STRING
32437
+ }), Editor({
32438
+ field_type: FieldType.SELECT,
32439
+ label: 'Display Mode',
32440
+ description: 'Visual display mode for options',
32441
+ validation: {
32442
+ options: [{
32443
+ label: 'Text (buttons with labels)',
32444
+ value: 'text'
32445
+ }, {
32446
+ label: 'Color (swatches)',
32447
+ value: 'color'
32448
+ }, {
32449
+ label: 'Image (patterns/textures)',
32450
+ value: 'image'
32451
+ }]
32452
+ }
32453
+ }), IsOptional(), IsString(), IsIn(['text', 'color', 'image']), __metadata("design:type", String)], OptionSelectorModel.prototype, "displayMode", void 0);
32454
+ __decorate([Field({
32455
+ defaultValue: 'grid',
32456
+ dataType: DataType.STRING
32457
+ }), Editor({
32458
+ field_type: FieldType.SELECT,
32459
+ label: 'Display Variant',
32460
+ description: 'How to display the selector',
32461
+ validation: {
32462
+ options: [{
32463
+ label: 'Buttons',
32464
+ value: 'buttons'
32465
+ }, {
32466
+ label: 'Dropdown',
32467
+ value: 'dropdown'
32468
+ }, {
32469
+ label: 'Grid',
32470
+ value: 'grid'
32471
+ }]
32472
+ }
32473
+ }), IsOptional(), IsString(), IsIn(['buttons', 'dropdown', 'grid']), __metadata("design:type", String)], OptionSelectorModel.prototype, "variant", void 0);
32474
+ __decorate([Field({
32475
+ defaultValue: 'wrap',
32476
+ dataType: DataType.STRING
32477
+ }), Editor({
32478
+ field_type: FieldType.SELECT,
32479
+ label: 'Layout Direction',
32480
+ description: 'Layout direction for buttons/grid variant',
32481
+ validation: {
32482
+ options: [{
32483
+ label: 'Horizontal',
32484
+ value: 'horizontal'
32485
+ }, {
32486
+ label: 'Vertical',
32487
+ value: 'vertical'
32488
+ }, {
32489
+ label: 'Wrap',
32490
+ value: 'wrap'
32491
+ }]
32492
+ }
32493
+ }), IsOptional(), IsString(), IsIn(['horizontal', 'vertical', 'wrap']), __metadata("design:type", String)], OptionSelectorModel.prototype, "layout", void 0);
32494
+ __decorate([Field({
32495
+ defaultValue: 'medium',
32496
+ dataType: DataType.STRING
32497
+ }), Editor({
32498
+ field_type: FieldType.SELECT,
32499
+ label: 'Visual Size',
32500
+ description: 'Size for color/image display modes',
32501
+ validation: {
32502
+ options: [{
32503
+ label: 'Small (32px)',
32504
+ value: 'small'
32505
+ }, {
32506
+ label: 'Medium (44px)',
32507
+ value: 'medium'
32508
+ }, {
32509
+ label: 'Large (56px)',
32510
+ value: 'large'
32511
+ }]
32512
+ }
32513
+ }), IsOptional(), IsString(), IsIn(['small', 'medium', 'large']), __metadata("design:type", String)], OptionSelectorModel.prototype, "visualSize", void 0);
32514
+ __decorate([Field({
32515
+ defaultValue: false,
32516
+ dataType: DataType.BOOLEAN
32517
+ }), Editor({
32518
+ field_type: FieldType.BOOLEAN,
32519
+ label: 'Show Label',
32520
+ description: 'Show label below visual (for color/image modes)'
32521
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], OptionSelectorModel.prototype, "showLabel", void 0);
32522
+ __decorate([Field({
32523
+ defaultValue: false,
32524
+ dataType: DataType.BOOLEAN
32525
+ }), Editor({
32526
+ field_type: FieldType.BOOLEAN,
32527
+ label: 'Disabled',
32528
+ description: 'Disable all option selections'
32529
+ }), IsOptional(), IsBoolean(), __metadata("design:type", Boolean)], OptionSelectorModel.prototype, "disabled", void 0);
32530
+ __decorate([Field({
32531
+ defaultValue: 'Select Option',
32532
+ dataType: DataType.STRING
32533
+ }), Editor({
32534
+ field_type: FieldType.TEXT,
32535
+ label: 'Label',
32536
+ description: 'Label text for the selector',
32537
+ placeholder: 'Select Option'
32538
+ }), IsOptional(), IsString(), __metadata("design:type", String)], OptionSelectorModel.prototype, "label", void 0);
32539
+ __decorate([Field({
32540
+ dataType: DataType.STRING
32541
+ }), Editor({
32542
+ field_type: FieldType.TEXT,
32543
+ label: 'Data Source',
32544
+ description: 'Data source for dynamic option loading',
32545
+ placeholder: 'product-options'
32546
+ }), IsOptional(), IsString(), __metadata("design:type", String)], OptionSelectorModel.prototype, "dataSource", void 0);
32547
+ __decorate([Field({
32548
+ dataType: DataType.OBJECT
32549
+ }), Editor({
32550
+ field_type: FieldType.TEXTAREA,
32551
+ label: 'Binding Options',
32552
+ description: 'Data binding configuration (JSON format)',
32553
+ placeholder: '{ "filter": {}, "sort": {} }'
32554
+ }), IsOptional(), __metadata("design:type", Object)], OptionSelectorModel.prototype, "bindingOptions", void 0);
32555
+ OptionSelectorModel = __decorate([Schema('OptionSelector', '1.0.0')], OptionSelectorModel);
32556
+
31437
32557
  /**
31438
32558
  * Schema for SafeSpan component - Safely renders HTML content with sanitization
31439
32559
  *
@@ -32312,4 +33432,4 @@ __decorate([Field({
32312
33432
  }), IsOptional(), __metadata("design:type", Boolean)], PageTemplateSchema.prototype, "indexable", void 0);
32313
33433
  PageTemplateSchema = __decorate([Schema('PageTemplate', '1.0.0')], PageTemplateSchema);
32314
33434
 
32315
- export { AVAILABLE_PALETTES, AccessibilityProvider, ActionModel, ActionType, AllPalettes, AppConfig, AppConfigBuilder, Article, ArticleModel, Breadcrumbs, Button, Captcha, CardListGrid, CardListGridModel, ChoiceInputField, ChoiceInputFieldModel, Code, CodeModel, CollapsibleLayout, CollapsibleLayoutView, ComponentTransformer$1 as ComponentTransformer, Container$8 as Container, Content, ContentModel, CoverImageHeader, CoverImageHeaderModel, DataProvider, DataProxy, DataTable, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, DimensionsProvider, ErrorBoundary, FeatureCard, FeatureCardActionModel, FeatureCardModel, FeatureGrid, FeatureGridModel, FeatureItemModel, Footer, FooterItemModel, FooterModel, FooterSectionModel, FormBlock, FormBlockModel, FormCheckbox, FormField, FormMethod, FormPage, FormSelect, GridCell, GridCellModel, GridLayout, GridLayoutModel, HeaderActionModel, HeroBlock, HeroBlockModel, Html, HtmlInputField, HtmlModel, Image, ImageModel, Logo, Markdown, MarkdownModel, MetadataItemModel, ModelView, NavigationProvider, Page, PageBannerHeader, PageBannerHeaderModel, PageTemplateSchema, PaletteAutumn, PaletteCosmic, PaletteDefault, PaletteOcean, PaletteProvider, PaletteSpring, PaletteSwitcher, PaletteSwitcherModel, PaletteWinter, PrintConfigSchema, PrintModeProvider, ProductCard, ProductCardActionModel, ProductCardModel, ProductLogo, ProductModel, QWICKAPP_COMPONENT, QwickApp, QwickAppsLogo, QwickIcon, ResponsiveMenu, SafeSpan, SafeSpanModel, Scaffold, SchemaFormRenderer, Section, SectionModel, SelectInputField, StatCard, SwitchInputField, T, Text$1 as Text, TextField, TextInputField, TextInputFieldModel, TextModel, ThemeProvider, ThemeSwitcher, ThemeSwitcherModel, ViewSchema, animationConfigs, applyCustomPalette, clearManifestCache, clearPaletteCache, clearUserPalettePreference, clearUserThemePreference, configurePaletteLoader, createAppConfig, createModelViewClass, createPaletteFromCurrentTheme, createSerializableView, defaultCollapsibleLayoutProps, deleteCustomPalette, exportPalette, extractTextFromReactNode, getAvailablePalettes, getCSSVariable, getComputedTheme, getCurrentPalette, getCurrentTheme, getCustomPalettes, getIconComponent, getIconEmoji, getLogger, getPaletteConfig, getPaletteFromManifest, getPaletteName, getRegisteredIcons, getSystemTheme, getThemePerformanceStats, hasIcon, iconMap, importPalette, initializePalette, initializeTheme, isCollapsibleLayoutProps, isPaletteLoaded, loadPalette, loadPaletteManifest, loadUserPalettePreference, loadUserThemePreference, logThemePerformanceStats, loggers, preloadPalettes, registerCustomPalette, registerIcon, resetThemePerformanceStats, resolveDimension, resolveDimensions, resolveSpacing, resolveSpacingProps, saveCustomPalette, savePalettePreference, saveThemePreference, saveUserPalettePreference, saveUserThemePreference, setCSSVariable, setPalette, setTheme, spacingConfigs, t, toCssLength, useAccessibility, useBaseProps, useBreadcrumbs, useCollapsibleState, useData, useDataBinding, useDataContext, useDataProvider, useDimensions, useNavigation, usePageContext, usePalette, usePrintMode$1 as usePrintMode, usePrintMode as usePrintModeHook, useQwickApp, useResolveTemplate, useTemplate, useTheme, withAccessibility, withErrorBoundary };
33435
+ export { AVAILABLE_PALETTES, AccessibilityProvider, ActionModel, ActionType, AllPalettes, AppConfig, AppConfigBuilder, Article, ArticleModel, Breadcrumbs, Button, Captcha, CaptchaModel, CardListGrid, CardListGridModel, ChoiceInputField, ChoiceInputFieldModel, Code, CodeModel, CollapsibleLayout, CollapsibleLayoutView, ComponentTransformer$1 as ComponentTransformer, Container$8 as Container, Content, ContentModel, CoverImageHeader, CoverImageHeaderModel, DataProvider, DataProxy, DataTable, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, DimensionsProvider, ErrorBoundary, FeatureCard, FeatureCardActionModel, FeatureCardModel, FeatureGrid, FeatureGridModel, FeatureItemModel, Footer, FooterItemModel, FooterModel, FooterSectionModel, FormBlock, FormBlockModel, FormCheckbox, FormCheckboxModel, FormField, FormFieldModel, FormMethod, FormPage, FormSelect, FormSelectModel, GalleryImageModel, GridCell, GridCellModel, GridLayout, GridLayoutModel, HeaderActionModel, HeroBlock, HeroBlockModel, Html, HtmlInputField, HtmlModel, Image, ImageGallery, ImageGalleryModel, ImageModel, Logo, Markdown, MarkdownModel, MetadataItemModel, ModelView, NavigationProvider, OptionSelector, OptionSelectorModel, Page, PageBannerHeader, PageBannerHeaderModel, PageTemplateSchema, PaletteAutumn, PaletteCosmic, PaletteDefault, PaletteOcean, PaletteProvider, PaletteSpring, PaletteSwitcher, PaletteSwitcherModel, PaletteWinter, PrintConfigSchema, PrintModeProvider, ProductCard, ProductCardActionModel, ProductCardModel, ProductLogo, ProductModel, QWICKAPP_COMPONENT, QwickApp, QwickAppsLogo, QwickIcon, ResponsiveMenu, SafeSpan, SafeSpanModel, Scaffold, SchemaFormRenderer, Section, SectionModel, SelectInputField, SelectOptionModel, StatCard, SwitchInputField, T, Text$1 as Text, TextField, TextInputField, TextInputFieldModel, TextModel, ThemeProvider, ThemeSwitcher, ThemeSwitcherModel, ViewSchema, animationConfigs, applyCustomPalette, clearManifestCache, clearPaletteCache, clearUserPalettePreference, clearUserThemePreference, configurePaletteLoader, createAppConfig, createModelViewClass, createPaletteFromCurrentTheme, createSerializableView, defaultCollapsibleLayoutProps, deleteCustomPalette, exportPalette, extractTextFromReactNode, getAvailablePalettes, getCSSVariable, getComputedTheme, getCurrentPalette, getCurrentTheme, getCustomPalettes, getIconComponent, getIconEmoji, getLogger, getPaletteConfig, getPaletteFromManifest, getPaletteName, getRegisteredIcons, getSystemTheme, getThemePerformanceStats, hasIcon, iconMap, importPalette, initializePalette, initializeTheme, isCollapsibleLayoutProps, isPaletteLoaded, loadPalette, loadPaletteManifest, loadUserPalettePreference, loadUserThemePreference, logThemePerformanceStats, loggers, preloadPalettes, registerCustomPalette, registerIcon, resetThemePerformanceStats, resolveDimension, resolveDimensions, resolveSpacing, resolveSpacingProps, saveCustomPalette, savePalettePreference, saveThemePreference, saveUserPalettePreference, saveUserThemePreference, setCSSVariable, setPalette, setTheme, spacingConfigs, t, toCssLength, useAccessibility, useBaseProps, useBreadcrumbs, useCollapsibleState, useData, useDataBinding, useDataContext, useDataProvider, useDimensions, useNavigation, usePageContext, usePalette, usePrintMode$1 as usePrintMode, usePrintMode as usePrintModeHook, useQwickApp, useResolveTemplate, useTemplate, useTheme, withAccessibility, withErrorBoundary };