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