@pixelated-tech/components 3.11.2 → 3.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -106
- package/dist/components/admin/site-health/site-health-axe-core.integration.js +1 -1
- package/dist/components/admin/site-health/site-health-github.integration.js +0 -1
- package/dist/components/general/tiles.css +132 -32
- package/dist/components/general/tiles.js +12 -2
- package/dist/components/sitebuilder/form/formbuilder.js +2 -1
- package/dist/components/sitebuilder/form/formextractor.js +2 -1
- package/dist/components/sitebuilder/form/formutils.js +13 -2
- package/dist/config/pixelated.config.json.enc +1 -1
- package/dist/scripts/config-vault.js +7 -5
- package/dist/scripts/config-vault.ts +7 -5
- package/dist/scripts/pixelated-eslint-plugin.js +300 -0
- package/dist/types/components/admin/site-health/site-health-axe-core.integration.d.ts +1 -63
- package/dist/types/components/admin/site-health/site-health-axe-core.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-github.integration.d.ts +1 -6
- package/dist/types/components/admin/site-health/site-health-github.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-security.integration.d.ts +1 -8
- package/dist/types/components/admin/site-health/site-health-security.integration.d.ts.map +1 -1
- package/dist/types/components/admin/site-health/site-health-types.d.ts +2 -0
- package/dist/types/components/admin/site-health/site-health-types.d.ts.map +1 -1
- package/dist/types/components/general/tiles.d.ts +9 -0
- package/dist/types/components/general/tiles.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formbuilder.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formextractor.d.ts.map +1 -1
- package/dist/types/components/sitebuilder/form/formutils.d.ts +0 -5
- package/dist/types/components/sitebuilder/form/formutils.d.ts.map +1 -1
- package/dist/types/scripts/pixelated-eslint-plugin.d.ts +124 -0
- package/dist/types/scripts/pixelated-eslint-plugin.d.ts.map +1 -1
- package/dist/types/stories/general/tiles.stories.d.ts +12 -0
- package/dist/types/stories/general/tiles.stories.d.ts.map +1 -1
- package/dist/types/stories/sitebuilder/form.honeypot.stories.d.ts.map +1 -1
- package/dist/types/tests/components/general/sitemap.test.d.ts.map +1 -0
- package/dist/types/tests/pixelated-eslint-plugin.exports.test.d.ts +2 -0
- package/dist/types/tests/pixelated-eslint-plugin.exports.test.d.ts.map +1 -0
- package/package.json +5 -5
- package/dist/components/general/sitemap.test.js +0 -19
- package/dist/types/components/general/sitemap.test.d.ts.map +0 -1
- /package/dist/types/{components → tests/components}/general/sitemap.test.d.ts +0 -0
package/README.md
CHANGED
|
@@ -85,8 +85,8 @@ Pixelated Components is committed to creating inclusive web experiences. All com
|
|
|
85
85
|
## 📦 Installation & Setup
|
|
86
86
|
|
|
87
87
|
### Requirements
|
|
88
|
-
- **React**:
|
|
89
|
-
- **Next.js**:
|
|
88
|
+
- **React**: 19.0 or higher
|
|
89
|
+
- **Next.js**: 16.0 or higher
|
|
90
90
|
- **Node.js**: 18.0 or higher
|
|
91
91
|
- **TypeScript**: 4.9 or higher (optional, but recommended)
|
|
92
92
|
|
|
@@ -105,10 +105,10 @@ pnpm add @pixelated-tech/components
|
|
|
105
105
|
|
|
106
106
|
### Peer Dependencies
|
|
107
107
|
|
|
108
|
-
This library requires the following peer dependencies (install if not already present):
|
|
108
|
+
This library requires the following peer dependencies (install if not already present). Versions in examples match the package's peerDependency policy:
|
|
109
109
|
|
|
110
110
|
```bash
|
|
111
|
-
npm install react react-dom prop-types
|
|
111
|
+
npm install react@^19 react-dom@^19 next@^16 prop-types
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
### TypeScript Support
|
|
@@ -162,86 +162,12 @@ npm run dev
|
|
|
162
162
|
|
|
163
163
|
Visit `http://localhost:3006` to explore the admin interface and see components in action.
|
|
164
164
|
|
|
165
|
-
###
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
- **Loading** - Progress indicators and loading states
|
|
172
|
-
- **MicroInteractions** - Subtle animations and interaction effects
|
|
173
|
-
- **Modal** - Dialog overlays and popups
|
|
174
|
-
- **Semantic** - Semantic HTML structure components
|
|
175
|
-
- **SidePanel** - Slide-out panel component for additional content
|
|
176
|
-
- **Table** - Data display and table components
|
|
177
|
-
|
|
178
|
-
### CMS Integration
|
|
179
|
-
Headless CMS and content management components:
|
|
180
|
-
- **WordPress** - Blog post integration and display with automatic Photon CDN URL processing
|
|
181
|
-
- **Contentful** - Headless CMS components and utilities with delivery and management APIs
|
|
182
|
-
- **PageBuilder** - Dynamic page construction from JSON
|
|
183
|
-
- **PageEngine** - Advanced page rendering with Contentful integration
|
|
184
|
-
|
|
185
|
-
### UI Components
|
|
186
|
-
User interface and interaction components:
|
|
187
|
-
- **Carousel** - Image and content sliders (Hero, Reviews, Portfolio)
|
|
188
|
-
- **Forms** - Form builder, validation, and emailer components
|
|
189
|
-
- **FormBuilder** - Advanced form construction and configuration
|
|
190
|
-
- **FormComponents** - Individual form field components and utilities
|
|
191
|
-
- **FormEngine** - Form rendering and processing engine
|
|
192
|
-
- **Menu** - Navigation components (Simple, Accordion, Expando)
|
|
193
|
-
- **Tab** - Tabbed interface component for organizing content
|
|
194
|
-
- **Tiles** - Image grid and tile layouts
|
|
195
|
-
- **FontSelector** - Font selection and Google Fonts integration
|
|
196
|
-
- **CompoundFontSelector** - Advanced font selection with multiple font families
|
|
197
|
-
|
|
198
|
-
### Development Tools
|
|
199
|
-
Components for development, configuration, and site building:
|
|
200
|
-
- **ComponentPropertiesForm** - Form for editing component properties
|
|
201
|
-
- **ComponentSelector** - Component selection interface
|
|
202
|
-
- **ComponentTree** - Visual component hierarchy display
|
|
203
|
-
- **ConfigBuilder** - Interactive configuration builder for site settings, metadata, routes, and visual design tokens
|
|
204
|
-
- **ConfigEngine** - Configuration processing and validation engine
|
|
205
|
-
- **PageBuilderUI** - User interface for page building
|
|
206
|
-
- **SaveLoadSection** - Save and load functionality for configurations
|
|
207
|
-
|
|
208
|
-
### SEO & Schema
|
|
209
|
-
Search engine optimization and structured data:
|
|
210
|
-
- **404** - Custom 404 error page component
|
|
211
|
-
- **FAQAccordion** - Interactive FAQ component with schema.org markup and search
|
|
212
|
-
- **GoogleAnalytics** - Google Analytics integration
|
|
213
|
-
- **GoogleMap** - Interactive Google Maps component
|
|
214
|
-
- **GoogleSearch** - Google Custom Search integration
|
|
215
|
-
- **JSON-LD** - Structured data schemas (LocalBusiness, Recipe, BlogPosting, etc.)
|
|
216
|
-
- **Manifest** - Web app manifest generation
|
|
217
|
-
- **MetaTags** - Dynamic meta tag injection
|
|
218
|
-
- **SchemaBlogPosting** - Blog post structured data
|
|
219
|
-
- **SchemaLocalBusiness** - Local business structured data
|
|
220
|
-
- **SchemaRecipe** - Recipe structured data
|
|
221
|
-
- **SchemaServices** - Services structured data
|
|
222
|
-
- **SchemaWebsite** - Website structured data
|
|
223
|
-
- **Sitemap** - XML sitemap generation
|
|
224
|
-
- **Social Cards** - Open Graph and Twitter card generation
|
|
225
|
-
- **BuzzwordBingo** - Interactive buzzword bingo game
|
|
226
|
-
- **Markdown** - Markdown rendering component
|
|
227
|
-
- **Recipe** - Recipe display component
|
|
228
|
-
- **Resume** - Resume/CV display component
|
|
229
|
-
- **Timeline** - Timeline visualization component
|
|
230
|
-
|
|
231
|
-
### Third-Party Integrations
|
|
232
|
-
External service integrations:
|
|
233
|
-
- **Calendly** - Scheduling and appointment booking
|
|
234
|
-
- **Cloudinary** - Image optimization and delivery
|
|
235
|
-
- **GoogleReviews** - Google business reviews integration
|
|
236
|
-
- **Gravatar** - User avatar integration
|
|
237
|
-
- **HubSpot** - CRM and marketing automation
|
|
238
|
-
- **Instagram** - Social media image integration
|
|
239
|
-
- **Flickr** - Photo sharing integration
|
|
240
|
-
- **PayPal** - Payment processing
|
|
241
|
-
- **ShoppingCart** - E-commerce shopping cart functionality
|
|
242
|
-
- **eBay** - Store listings and shopping cart
|
|
243
|
-
- **NerdJokes** - Entertainment content integration
|
|
244
|
-
- **Yelp** - Business reviews and ratings
|
|
165
|
+
### Component index
|
|
166
|
+
The full component index and API reference live in `docs/components.md` (single source-of-truth). For interactive exploration, run Storybook: `npm run storybook`.
|
|
167
|
+
|
|
168
|
+
- Quick link: [Component API reference](docs/components.md)
|
|
169
|
+
|
|
170
|
+
If you want to browse individual components interactively, run Storybook: `npm run storybook`.
|
|
245
171
|
|
|
246
172
|
|
|
247
173
|
### Utilities
|
|
@@ -268,28 +194,6 @@ Comprehensive site health monitoring and analytics:
|
|
|
268
194
|
- **SiteHealthDependencyVulnerabilities** - Dependency security scanning
|
|
269
195
|
|
|
270
196
|
|
|
271
|
-
## 🎨 Visual Design Configuration
|
|
272
|
-
|
|
273
|
-
The ConfigBuilder now includes a **Visual Design** tab that allows users to configure visual design tokens such as colors, fonts, spacing, and other design system variables. These tokens are stored in the `routes.json` file under the `visualdesign` object and can be used throughout your application for consistent theming.
|
|
274
|
-
|
|
275
|
-
### Features:
|
|
276
|
-
- **Color Management**: Primary, secondary, accent colors with color picker inputs
|
|
277
|
-
- **Typography**: Font family and base font size settings
|
|
278
|
-
- **Spacing & Layout**: Border radius, box shadows, transitions
|
|
279
|
-
- **Form-Based Editing**: User-friendly form interface powered by FormEngine
|
|
280
|
-
- **JSON Storage**: Design tokens stored as flattened key-value pairs in routes.json
|
|
281
|
-
|
|
282
|
-
### Usage:
|
|
283
|
-
```tsx
|
|
284
|
-
import { ConfigBuilder } from '@pixelated-tech/components';
|
|
285
|
-
|
|
286
|
-
function MyConfigPage() {
|
|
287
|
-
return <ConfigBuilder />;
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
The visual design tokens can be accessed in your components via the config context or directly from the routes.json file.
|
|
292
|
-
|
|
293
197
|
|
|
294
198
|
## � Quick Start
|
|
295
199
|
|
|
@@ -336,6 +240,13 @@ See our detailed [Roadmap](docs/roadmap.md) for planned improvements and refacto
|
|
|
336
240
|
|
|
337
241
|
See our comprehensive [Testing Documentation](docs/testing.md) for test coverage, setup, and strategies.
|
|
338
242
|
|
|
243
|
+
Quick conventions:
|
|
244
|
+
- Unit & integration tests → `src/tests` (filename: `*.test.{ts,tsx}`)
|
|
245
|
+
- Shared harnesses / fixtures → `src/test`
|
|
246
|
+
- Storybook stories & `play()` tests → `src/stories` (run with `npm run storybook`)
|
|
247
|
+
|
|
248
|
+
Following these locations keeps CI discovery and story-driven QA consistent across the monorepo.
|
|
249
|
+
|
|
339
250
|
|
|
340
251
|
<!-- CONTRIBUTING -->
|
|
341
252
|
## Contributing
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import puppeteer from 'puppeteer';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
|
+
import { getFullPixelatedConfig } from '../../config/config';
|
|
5
6
|
const debug = false;
|
|
6
7
|
export async function performAxeCoreAnalysis(url, runtime_env = 'auto') {
|
|
7
8
|
try {
|
|
@@ -66,7 +67,6 @@ export async function performAxeCoreAnalysis(url, runtime_env = 'auto') {
|
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
import { getFullPixelatedConfig } from '../../config/config';
|
|
70
70
|
/**
|
|
71
71
|
* runAxeCoreAnalysis(url, runtime_env)
|
|
72
72
|
*
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { getFullPixelatedConfig } from '../../config/config';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
// Version extraction: we derive a version from commit messages (e.g., v1.2.3) instead of fetching tags and fuzzy-matching.
|
|
5
4
|
// Debug logging is off by default. Set to true/false here (do not use env vars).
|
|
6
5
|
const debug = false;
|
|
7
6
|
/**
|
|
@@ -11,12 +11,9 @@
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.tile-image {
|
|
14
|
-
position: relative;
|
|
15
|
-
aspect-ratio: 1;
|
|
16
14
|
border: 2px solid #CCC;
|
|
17
15
|
/* border-radius: 20px; */
|
|
18
16
|
overflow: hidden;
|
|
19
|
-
margin: 10px;
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
.tile-image.clickable {
|
|
@@ -26,23 +23,11 @@
|
|
|
26
23
|
.tile-image img {
|
|
27
24
|
width: 100%;
|
|
28
25
|
height: 100% !important;
|
|
29
|
-
position: relative;
|
|
30
|
-
display: inline-block;
|
|
31
26
|
align-self: start;
|
|
32
27
|
object-fit: cover;
|
|
33
28
|
}
|
|
34
29
|
|
|
35
30
|
.tile-image-overlay {
|
|
36
|
-
visibility: hidden;
|
|
37
|
-
position: absolute;
|
|
38
|
-
width: 0%;
|
|
39
|
-
height: 100%;
|
|
40
|
-
bottom: 0;
|
|
41
|
-
left: 0;
|
|
42
|
-
display: inline-block;
|
|
43
|
-
background: rgba(51, 102, 153, .7);
|
|
44
|
-
transition: all 0.25s ease-in-out;
|
|
45
|
-
/* All other styling - see example */
|
|
46
31
|
img {
|
|
47
32
|
vertical-align: top; /* Default is baseline, this fixes a common alignment issue */
|
|
48
33
|
}
|
|
@@ -54,27 +39,10 @@
|
|
|
54
39
|
cursor: pointer;
|
|
55
40
|
}
|
|
56
41
|
|
|
57
|
-
.tile-image:hover .tile-image-overlay {
|
|
58
|
-
visibility: visible;
|
|
59
|
-
width: 100% !important;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
42
|
.tile-image-overlay-text {
|
|
63
|
-
position: absolute;
|
|
64
43
|
padding: 20px;
|
|
65
|
-
left: 0;
|
|
66
|
-
bottom: 0;
|
|
67
|
-
color: white;
|
|
68
44
|
font-size: 20px;
|
|
69
45
|
font-weight: bold;
|
|
70
|
-
visibility: hidden;
|
|
71
|
-
transition: visibility 0s ease-in-out;
|
|
72
|
-
transition-delay: 0s;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.tile-image:hover .tile-image-overlay-text {
|
|
76
|
-
visibility: visible;
|
|
77
|
-
transition-delay: 0.25s;
|
|
78
46
|
}
|
|
79
47
|
|
|
80
48
|
.tile-image-overlay-title {
|
|
@@ -85,3 +53,135 @@
|
|
|
85
53
|
font-size: 16px;
|
|
86
54
|
font-weight: initial;
|
|
87
55
|
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
/* ====== OVERLAY VARIANT (CSS-only) ======
|
|
61
|
+
- Applied by adding `variant="overlay"` to <Tiles/> (adds `.overlay` to each `.tile`)
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
.tile.overlay {
|
|
65
|
+
|
|
66
|
+
.tile-image {
|
|
67
|
+
position: relative;
|
|
68
|
+
aspect-ratio: 1;
|
|
69
|
+
margin: 10px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.tile-image img {
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: 100% !important;
|
|
75
|
+
position: relative;
|
|
76
|
+
display: inline-block;
|
|
77
|
+
align-self: start;
|
|
78
|
+
object-fit: cover;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.tile-image-overlay {
|
|
82
|
+
visibility: hidden;
|
|
83
|
+
position: absolute;
|
|
84
|
+
width: 0%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
bottom: 0;
|
|
87
|
+
left: 0;
|
|
88
|
+
display: inline-block;
|
|
89
|
+
background: rgba(51, 102, 153, .7);
|
|
90
|
+
transition: all 0.25s ease-in-out;
|
|
91
|
+
/* All other styling - see example */
|
|
92
|
+
img {
|
|
93
|
+
vertical-align: top; /* Default is baseline, this fixes a common alignment issue */
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.tile-image:hover .tile-image-overlay {
|
|
98
|
+
visibility: visible;
|
|
99
|
+
width: 100% !important;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.tile-image-overlay-text {
|
|
103
|
+
position: absolute;
|
|
104
|
+
padding: 20px;
|
|
105
|
+
left: 0;
|
|
106
|
+
bottom: 0;
|
|
107
|
+
color: white;
|
|
108
|
+
font-size: 20px;
|
|
109
|
+
font-weight: bold;
|
|
110
|
+
visibility: hidden;
|
|
111
|
+
transition: visibility 0s ease-in-out;
|
|
112
|
+
transition-delay: 0s;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.tile-image:hover .tile-image-overlay-text {
|
|
116
|
+
visibility: visible;
|
|
117
|
+
transition-delay: 0.25s;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.tile-image-overlay-title {
|
|
121
|
+
margin-bottom: 10px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.tile-image-overlay-body{
|
|
125
|
+
font-size: 16px;
|
|
126
|
+
font-weight: initial;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
/* ====== CAPTION VARIANT (CSS-only) ======
|
|
136
|
+
- Applied by adding `variant="caption"` to <Tiles/> (adds `.caption` to each `.tile`)
|
|
137
|
+
*/
|
|
138
|
+
.tile.caption {
|
|
139
|
+
* {
|
|
140
|
+
visibility: visible;
|
|
141
|
+
display: block;
|
|
142
|
+
position: relative;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.tile-image {
|
|
146
|
+
aspect-ratio: auto;
|
|
147
|
+
border-radius: 10px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.tile-image img {
|
|
151
|
+
width: 100%;
|
|
152
|
+
height: 100% !important;
|
|
153
|
+
align-self: start;
|
|
154
|
+
object-fit: cover;
|
|
155
|
+
aspect-ratio: 1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.tile-image-overlay {
|
|
159
|
+
background-color: #EEEEEE;
|
|
160
|
+
height: 100px !important;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.tile-image-overlay,
|
|
164
|
+
.tile-image-overlay * {
|
|
165
|
+
width: 100% !important;
|
|
166
|
+
height: auto;
|
|
167
|
+
transition: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.tile-image-overlay-title {
|
|
171
|
+
margin-bottom: 0px;
|
|
172
|
+
color: black;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.tile-image-overlay-text {
|
|
176
|
+
transition: none;
|
|
177
|
+
color: black;
|
|
178
|
+
padding: 10px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.tile-image-overlay-body{
|
|
182
|
+
font-size: var(--font-size-base);
|
|
183
|
+
font-weight: bold;
|
|
184
|
+
color: black;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
}
|
|
@@ -6,15 +6,21 @@ import { SmartImage } from "./smartimage";
|
|
|
6
6
|
import { usePixelatedConfig } from '../config/config.client';
|
|
7
7
|
import "../../css/pixelated.grid.scss";
|
|
8
8
|
import "./tiles.css";
|
|
9
|
+
export const TilesVariants = ['caption', 'overlay'];
|
|
9
10
|
Tiles.propTypes = {
|
|
10
11
|
cards: PropTypes.array.isRequired,
|
|
11
12
|
rowCount: PropTypes.number,
|
|
12
13
|
imgClick: PropTypes.func,
|
|
14
|
+
/**
|
|
15
|
+
* Optional visual variant. Allowed values are enumerated so consumers get
|
|
16
|
+
* a discoverable, typed API.
|
|
17
|
+
*/
|
|
18
|
+
variant: PropTypes.oneOf(TilesVariants),
|
|
13
19
|
};
|
|
14
20
|
export function Tiles(props) {
|
|
15
21
|
const rowCount = props.rowCount ?? 2;
|
|
16
22
|
if (props.cards && props.cards.length > 0) {
|
|
17
|
-
return (_jsx("div", { className: "tiles-container", children: _jsx("div", { className: `tile-container row-${rowCount}col`, children: props.cards.map((card, i) => (_jsx("div", { className: "gridItem", children: _jsx(Tile, { index: i, cardLength: props.cards.length, link: card.link, image: card.image, imageAlt: card.imageAlt, bodyText: card.bodyText, imgClick: props.imgClick }) }, i))) }) }));
|
|
23
|
+
return (_jsx("div", { className: "tiles-container", children: _jsx("div", { className: `tile-container row-${rowCount}col`, children: props.cards.map((card, i) => (_jsx("div", { className: "gridItem", children: _jsx(Tile, { index: i, cardLength: props.cards.length, link: card.link, image: card.image, imageAlt: card.imageAlt, bodyText: card.bodyText, imgClick: props.imgClick, variant: (props.variant ?? "overlay") }) }, i))) }) }));
|
|
18
24
|
}
|
|
19
25
|
else {
|
|
20
26
|
return (_jsx(Loading, {}));
|
|
@@ -29,12 +35,16 @@ Tile.propTypes = {
|
|
|
29
35
|
imageAlt: PropTypes.string,
|
|
30
36
|
bodyText: PropTypes.string,
|
|
31
37
|
imgClick: PropTypes.func,
|
|
38
|
+
/** 'caption' - visual caption beneath image (prefers bodyText, falls back to imageAlt) */
|
|
39
|
+
variant: PropTypes.oneOf(TilesVariants),
|
|
32
40
|
};
|
|
33
41
|
function Tile(props) {
|
|
34
42
|
const config = usePixelatedConfig();
|
|
35
43
|
const imgClick = props.imgClick;
|
|
44
|
+
const captionText = (props.bodyText && props.bodyText.length > 0) ? props.bodyText : (props.imageAlt ?? "");
|
|
36
45
|
const tileBody = _jsxs("div", { className: "tile-image" + (imgClick ? " clickable" : ""), children: [_jsx(SmartImage, { src: props.image, title: props?.imageAlt ?? undefined, alt: props?.imageAlt ?? "", onClick: imgClick ? (event) => imgClick(event, props.image) : undefined, cloudinaryEnv: config?.cloudinary?.product_env ?? undefined }), _jsx("div", { className: "tile-image-overlay", children: _jsxs("div", { className: "tile-image-overlay-text", children: [_jsx("div", { className: "tile-image-overlay-title", children: props.imageAlt }), _jsx("div", { className: "tile-image-overlay-body", children: props.bodyText })] }) })] });
|
|
37
|
-
|
|
46
|
+
const rootClass = `tile${(props.variant) ? ' ' + props.variant : ''}`;
|
|
47
|
+
return (_jsx("div", { className: rootClass, id: 'tile-' + props.index, children: props.link ?
|
|
38
48
|
_jsx("a", { href: props.link, className: "tileLink", children: tileBody })
|
|
39
49
|
:
|
|
40
50
|
tileBody }));
|
|
@@ -3,8 +3,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
5
|
import * as FC from './formcomponents';
|
|
6
|
-
import { mapTypeToComponent, generateTypeField
|
|
6
|
+
import { mapTypeToComponent, generateTypeField } from './formutils';
|
|
7
7
|
import { FormEngine } from './formengine';
|
|
8
|
+
const debug = false;
|
|
8
9
|
/* ===== FORM BUILDER =====
|
|
9
10
|
Display all the components for a Form Builder -
|
|
10
11
|
Element Buttons, Element Details, and the Form */
|
|
@@ -3,8 +3,9 @@ import { useState, useEffect } from 'react';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import * as FC from './formcomponents';
|
|
5
5
|
import * as FVF from './formfieldvalidations';
|
|
6
|
-
import { capitalize, attributeMap
|
|
6
|
+
import { capitalize, attributeMap } from './formutils';
|
|
7
7
|
import { FormEngine } from './formengine';
|
|
8
|
+
const debug = false;
|
|
8
9
|
/*
|
|
9
10
|
===== FORM EXTRACT =====
|
|
10
11
|
Submit a page URL of a form to extract all form elements and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Shared utility functions for form components
|
|
2
2
|
import { generateKey, capitalize, attributeMap } from '../../general/utilities';
|
|
3
|
-
|
|
3
|
+
const debug = false;
|
|
4
4
|
/**
|
|
5
5
|
* Maps input type to form component name
|
|
6
6
|
*/
|
|
@@ -18,8 +18,19 @@ export function mapTypeToComponent(myType) {
|
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
20
|
* Generates field JSON for form building
|
|
21
|
+
*
|
|
22
|
+
* NOTE: This implementation is currently unused by other modules in-repo and
|
|
23
|
+
* is exported by the package barrel which previously caused a duplicate
|
|
24
|
+
* export collision with `componentGeneration.generateFieldJSON` during
|
|
25
|
+
* Storybook's webpack build. To avoid accidental breakage for external
|
|
26
|
+
* consumers we are making this implementation internal (non-exported)
|
|
27
|
+
* and marking it for removal in a future maintenance sweep.
|
|
28
|
+
*
|
|
29
|
+
* TODO (cleanup): remove this function and any remaining aliases once
|
|
30
|
+
* consumers have migrated — see `docs/roadmap.md` (Refactoring & Cleanup).
|
|
31
|
+
* @deprecated internal-only — slated for removal
|
|
21
32
|
*/
|
|
22
|
-
|
|
33
|
+
function generateFieldJSON(component, type) {
|
|
23
34
|
const form = {};
|
|
24
35
|
form.fields = [];
|
|
25
36
|
// Common fields for all components
|
|
@@ -1 +1 @@
|
|
|
1
|
-
pxl:v1:
|
|
1
|
+
pxl:v1:b15a24756358d6e6b02272a2:9bfd2086414fa1eaa92153908ed0e15d:ab8b7769a766de9be76c08c748e59ffeb147312bb908995fd88456c5cc76366350bf44d28f9b3ed9ebabb70ca106e4fa9196e559e81ce591b6764abce5415bb5013dc07538d6d0d92a377d46c1a6f2f96327c06d269053672fb532a274bc5b8483bf06b8a9f6e16d9733be3c5033a967d91527ffb53f1e5c65dfd66b983e4e3f2ec086e01ddd68a0a4d85a2b3dc3bef21024e50c11b2c8256c8dd1b2f2c8c71aaba175063b61f5253d05c0c2847ecf4ddb6b40f8aa9af5de027598b1f747b72cdd6ba85025fdf30f35d47f9c10de625209bd28ea11bd73decc15f1de580be1b155032b2857ee9ac8212aeb943c42a773fa75a0867413c455cce15bc77406bf2b5ba0f5da75cd14735f53b3d22962b27c04c418bcb7e241850f64a873649c3a52c67a84db2f9a3c4a7605ec5114ad1f74a0eef57d57b1dd98d87b144336d516b2d48324df0143e5687abdbd5ffbb9a0751e5f91577742fe460c390c519d73b3da3da2c1a4d32a738875106a58c91b6b04016eba50f57a026c9d67312bdfb53992ac025e503ee818aed29959337947e1d0d81e6cccd0d1a921cfe31d225ce744cc82340ce4af6aa308677cee985a7e7ae1d1b7d21274ca8264ee6481e5f001d1d4dea91dc0eb787d2cf1b990d9690e9bb83489d0e354d1071bff8a1668550303f04256f7e60736146a5da09e15b65d467af7194ece67feefc45736d009f8043d76c30b9263e04224977d8b9ce64b5e6317e6f3a604c76b1290ffa410e51dd069258321448675382907f32c6b51dfede27fa6db5244952f883c57b8d6cf9572e6cfa7a4d973f86c1ab3b54a7bf765deee12ea7d381eef24e1424f09dcdddd219930826dcc69d924ccd1937538b4edb8e347da359b638aeb475b38b08307d5ec568b959ac9c4dfd1889bf2c963b7bc0b65bdbef0d89a75b026ca4af6e87641ff604ae2da4b3c19a1c6a3a3f32ad870343f342d609946392d3e540044d7df067b00eb7ec16284a9b42439f853bdd6492163382d1e90d6e24e46b5ff1061cb51e8089ddfa3985775d03551f082cef25b0feeda0a9cc416a25f01d71f4797332b654895ee0766735dc02329e48f56d4583eb5fb9ca9e0f9c71b7ac21b3abecb55edca90731d7d69c16dbd31c0f01f3842fc1b4322383932c70e0131e6a723d95f26adbe8777f9d0bfaa75f310b411d9203689a8e13238328f04ae7ebb34e9212b77edd89b54f6924654a31d17c646a24bff9a096305be689c10a1dad1830199679568f5054616fe18572f44aac4846c3649e6b58509b6096efdbbf5a0bbcec5e97a48fb7497ab2d74376e76f269366b1d5dfd426fbcace4ee5bf775e9c9b804eb87363c8f9394a96c703c84cef79d1a9ae846c537ffcbb5daaaf4efdab9c6cf2ba12f6df46b8ea62acefa01f1201432808758b38643e6154bb74d0b7af6f01461357b58e51c726df49dd59585ed034473469de5f9454aff9794c0f08af4e7a976de871a3e67a7769a2b7d69aea8438767a06dd12815471bfe359c274e8b3e9e9b0419712c85d59b1844034bdf2d486cd9cb94b875672acbcd0dcbb3156e5b52c69a4f0f2339c682183b31a7a0f0757b505fa4c33e31e4554f535d001b441daed3122f7a6d6fd9563ad55d71ef0c361bd908370f52d63c96488f3dd7aa1f480e562fb8275119e5b3c866e4536c5a1dbb6f3e89ccca9ccf44cd7f60ba5e2de6f68b8f22c6fec7ff146bb4eb84230712ea1638b515bfb5e00518fe4ab4c7465c4a0b7b422fa9ecfb3dc7f5ff44915dd3aa982e6f9304e3068446e45dfa4e61eb6c7649cd8b4918ac3c369f42a7d71a9ce69afb63b9a4bd421c6e65e1e781b11aee3d22d85a776f8306a80d00956ca44163c7c7517d8fdb916808f42714bde340d39dc85aa606507f4f8942b28aa596ee67b478eab4439f3f8462d07a37555a8405eface5b4e45fe62c779e818c0e0f2ffb1c8885a2873e08a39e6731a421a4edd82fd0f18b16a3ed249e4a8fe3e41ea1c20e2d886a57ca64115b85c494879f9d1f0538c67c87c32d38225c2516b5d57138a0ac1741b88a076952042c75ea75a344e3154ce7729bfe524afc79ba82b5e80f0cac64d15d9af1e0fc4065415613f72942013db82178e9458d598c1e4c933ff7be954ad45e903fc1c0fa97bd1af49aa9cb6bf5ab4a14e801cfb2f9ebc3a1116ee7ec210cc07e9dd5bbd40b286028f2a4f1859473cdcbfdefd782c4eea8484e238d90081b48b5c6010dd16069a95485095fbe0fbdf5b50ba89dea877fa254d6583958bba61bd01f5edd53b6182678cd5df5c26adecb0427ba8b4763f83d281c93a3fa220528b25b6f14cdd8978d86f2bb402b9d576b390edf2738b243dd7a334951199dc63effb2c826e70257d310e56848a85f2e47042f934a0937d4f0d5ffd8dc06822cd5a3cecd12b628842c3f4e994989a655af25e7170dc9d24bbe3dc244606e3f196d062240defafe6d8276e02cf2da35514fbf93e8a3457631af251b1d4d707986c85b88d34ee81e77f3f9ca8507c00319bacdf1458656d9dc4198d81db75333e232ecb1366c5aa51d0fe2053c33cac284f9be16c9a6994de0227f55fc944ddf6277be6f0fad647ab3f35fbf3a75c0432025d41773dea229c021d508f30f2771e04b37bfb6471ac26ff9ad282cb5454464f6b1d26d02fa86ea2c6727ed637a2f0622d84891324368cefdb4ac6b9726372cfb9be4f05f47ea0005f3d892f8ab4aeabb666001f120b87207801cf279625f94cdc3ae93ce019c631e18d0ea88d70c88464d94274a8ab767c4b959c598c5472b6263358c29599351f74d9c73375e921d2d239f1675dd55b02a0450d99f8d0b5d7a83a3559f133f1af11c21c4f639929cecb7dbf3d97d81b5b19260800977ecf63c2cda31c82960e2c8f20eee1cc803d3613d7b324dfd6c54176f39fcdda99cf4f90ad4366dccf12b35a095de628fb63fa40fe39cd7f87dc85e287c9a9b6636e4444bd47650d85d01b58c06174fe725bc7737b9d3fdf7c61da147fcb2ce39cb74514650a1a7266bd91a8eae5f76149bf6ce4332d235ca5509ff7d53e51480f0e89294ea83edb84d91bbd8deaba4dbc850bab27fdd2d8e01a9e8dc51a1cacb27fb9e6c551ea5c9d0994245384f21ca9b0de3594c7a597ad52bdbddb81b706ffd05dc21ba766bb8cd13a1de888af0217ff9905069c19a7ca0cf1ce3b9a5111caffd50f65a0a0d24982ffda39c7343d73b1992ec3a3c5048c6d96ebd1064be6c3cc65ee4bc843fc552f6b25cc960919c35c41910e354e7aa2fa6c00bbd8b605e666338378794e9ed210ac265e92c1958b4e6eaca420c0e546b135b2cf4cf25a206424a3619f6cd3fef71f6f34960ee36a0236711e8b1b2e4ac03f78d94d54975f798bfa8826e409de8790c0feda76c6f85c0275de2dd08302766147a06e105f48e9e5db0f820110d24ab91561bc3cf4eb27c60d21eaf81d38964fc0ece16418ab2b561c9c0acada88dfd577ff0a3762139efa8edc09a23b6c33fd47b0bb5b52fc7afd09e66cce984452133a15d2c4de8d4779511175c946fca6933b016191f96f7c3ba9f8cbac7fc1267c1f01777817424c38bde51842213e3e1e5d84333fb2d805da2860d57009908a80e0e012b9683808a2e1759b48c0b64b043a04a35bf962e082b041853f5c5d7466ea2f714b8f2422fd6162daeb4a236546e493b06f15edfe0d7869aeffbaafc8bf9a138301fc121783832aef1a5e17dd7e548421115135b26b56bdfc0f0322d99653b7a3bad31e3e34e032e1803b31e46a20c2c1232b10cd2020c06106c8f795b7241c6253d9080498cc60e7c7b93549522c0d0c5c33e3c87e6096096cde13c0233dde2c59d32e40b5f21d8b114f84fbe98df27cacb130353ab81aa531b1884d99fef4e115c60d7b110ef05300a90270d8d7e9d5a761465973b37d1f9c4ae569e80b08e900423aeb5bb839f066de9e687d97a8405482ffb14bc942cc909b1507f0a98b98b2e907cb522078da150d977814e3985359a4eaf4325c2f8f271da8bb7927b35862db461a7c10b88f95be8a1ffbb11c15b6615eecf9a48687c3106aba3245934f5900d3049bd704cc6439919fb085a51d19ec883801fa6156031cc17b1b608f2a9c64a505373b62d90fed060ba14390e9d7a1fcc48ed4c9f15879dc8f827095f73fe6a21558311c4dd4cac91d1f1c128e8e378ecf91b04ac87d92cd3d9026e8b4a9439254c98930a7987f3dc8e8dc84d330ed25f65207822b03896ce43c18ad1cf0d9abe6ca5d092f14a19a202600679353b041a6f9bbdc17791e527a9dcd223b034f983add3c57052ec62ae4b61f6c3b8e5099c3ec0aa8ce5d4f0e1f308ff46803c5c72a5f902d02b65d713101dc83a252dfdb0fd4c36cf14030221a34b993fcb4f3261eb9aa884eb7ebc41fcef9b72765e09b63e2fc818a80f7128b153e763883ef632c6f97b77ea84ab070d85d129eb7cf2bd3d44419fa271ca0531339d9a2470a7ff37dc2c6da56c08b7bbff47d47c9d5cec9f106b3a3f23c98b65128e995dd47251d21acff2566614ca911318ad0416f1658eb8d31956d8f5ff0d22ab4390fee5e3cdf251bbc113b68b847203c3d65edeb7feb7a929ea25f2153837acd99486cf3b368b15cbd2ca3fe377bd95ef17b4fb77d8e633b747adc89f2738741a794a6058b5cf94bbb4a8849d6a3de88de7649155ba279f41f36895ed5b2161710c541c1bcbfd64bde555fd35aa0ed950725d9c595447fb73b52d4ab4b1affc5756babe36a42649d24b121244d9205344ffe6668a097c5c4fc83dff002c3af4ca6f357dd184c864b6cda545301ae0e333cc0ebccdbf00cad40fa4b133f8961751746feb4eb45d1b426e2a02effc5d4eb0f39df08c2aff63db26575df75f827ef33e20db0e1775f3c08d3833812b15348fa8cf8aba7643926ba11a87d11c34981690811019e7d1c109e5ec9863b4c49b65a6df5126e26a2c5867432632bf15389c243af3eba40e75ddbba75b315ab387a4d27c2000c56ec136808505087389b4a81466d08a2e32ee7de86efedd17d5390bb14aa1e79dcbe4103eb1bca793ef5f4a0ccfa3fe60d1210ef26dd955fc0b59180eaf04fd258272b173815596bda4575788156e3408c2aaaecb99293e83b1d85b3857e5432c8e158738d92a11cd783cf4af
|
|
@@ -77,8 +77,8 @@ if (command === 'encrypt' || command === 'decrypt') {
|
|
|
77
77
|
* - Decrypt in-place and copy plaintext to .next/server/pixelated.config.json
|
|
78
78
|
* - Validate JSON and emit a concise success message
|
|
79
79
|
*/
|
|
80
|
-
function decryptPostBuild() {
|
|
81
|
-
const
|
|
80
|
+
function decryptPostBuild(opts = {}) {
|
|
81
|
+
const debug = opts.debug ?? false;
|
|
82
82
|
const candidates = [
|
|
83
83
|
path.join(process.cwd(), 'src/app/config/pixelated.config.json.enc'),
|
|
84
84
|
path.join(process.cwd(), 'src/config/pixelated.config.json.enc'),
|
|
@@ -92,7 +92,7 @@ function decryptPostBuild() {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
if (!foundEnc) {
|
|
95
|
-
if (
|
|
95
|
+
if (debug)
|
|
96
96
|
console.log('No encrypted config found; nothing to do.');
|
|
97
97
|
process.exit(0);
|
|
98
98
|
}
|
|
@@ -136,7 +136,7 @@ function decryptPostBuild() {
|
|
|
136
136
|
// Validate JSON
|
|
137
137
|
JSON.parse(decrypted);
|
|
138
138
|
console.log('Config injected into .next/server/pixelated.config.json');
|
|
139
|
-
if (
|
|
139
|
+
if (debug)
|
|
140
140
|
console.log(`Decrypted ${path.basename(foundEnc)} -> ${injectPath}`);
|
|
141
141
|
process.exit(0);
|
|
142
142
|
}
|
|
@@ -177,7 +177,9 @@ try {
|
|
|
177
177
|
console.log(`Successfully decrypted ${path.basename(targetPath)} -> ${path.basename(destPath)}`);
|
|
178
178
|
}
|
|
179
179
|
else if (command === 'postbuild' || command === 'post-build' || command === 'inject') {
|
|
180
|
-
|
|
180
|
+
// CLI-only debug opt-in: explicit flag (do NOT use env vars for debug)
|
|
181
|
+
const cliDebug = process.argv.includes('--debug') || process.argv.some(a => a.startsWith('--debug='));
|
|
182
|
+
decryptPostBuild({ debug: cliDebug });
|
|
181
183
|
}
|
|
182
184
|
else {
|
|
183
185
|
console.error(`Unknown command: ${command}`);
|
|
@@ -83,8 +83,8 @@ if (command === 'encrypt' || command === 'decrypt') {
|
|
|
83
83
|
* - Decrypt in-place and copy plaintext to .next/server/pixelated.config.json
|
|
84
84
|
* - Validate JSON and emit a concise success message
|
|
85
85
|
*/
|
|
86
|
-
function decryptPostBuild(): void {
|
|
87
|
-
const
|
|
86
|
+
function decryptPostBuild(opts: { debug?: boolean } = {}): void {
|
|
87
|
+
const debug = opts.debug ?? false;
|
|
88
88
|
const candidates = [
|
|
89
89
|
path.join(process.cwd(), 'src/app/config/pixelated.config.json.enc'),
|
|
90
90
|
path.join(process.cwd(), 'src/config/pixelated.config.json.enc'),
|
|
@@ -100,7 +100,7 @@ function decryptPostBuild(): void {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
if (!foundEnc) {
|
|
103
|
-
if (
|
|
103
|
+
if (debug) console.log('No encrypted config found; nothing to do.');
|
|
104
104
|
process.exit(0);
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -144,7 +144,7 @@ function decryptPostBuild(): void {
|
|
|
144
144
|
// Validate JSON
|
|
145
145
|
JSON.parse(decrypted);
|
|
146
146
|
console.log('Config injected into .next/server/pixelated.config.json');
|
|
147
|
-
if (
|
|
147
|
+
if (debug) console.log(`Decrypted ${path.basename(foundEnc)} -> ${injectPath}`);
|
|
148
148
|
process.exit(0);
|
|
149
149
|
} catch (err: any) {
|
|
150
150
|
console.error(`Post-build decrypt failed: ${err.message}`);
|
|
@@ -182,7 +182,9 @@ try {
|
|
|
182
182
|
atomicWrite(destPath, decrypted);
|
|
183
183
|
console.log(`Successfully decrypted ${path.basename(targetPath)} -> ${path.basename(destPath)}`);
|
|
184
184
|
} else if (command === 'postbuild' || command === 'post-build' || command === 'inject') {
|
|
185
|
-
|
|
185
|
+
// CLI-only debug opt-in: explicit flag (do NOT use env vars for debug)
|
|
186
|
+
const cliDebug = process.argv.includes('--debug') || process.argv.some(a => a.startsWith('--debug='));
|
|
187
|
+
decryptPostBuild({ debug: cliDebug });
|
|
186
188
|
} else {
|
|
187
189
|
console.error(`Unknown command: ${command}`);
|
|
188
190
|
process.exit(1);
|