@deneb-ui/create-template 2.0.107 → 2.0.109
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/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -162,6 +162,24 @@ Edit `src/data/site-data.json` under `template.structure.theme`:
|
|
|
162
162
|
```
|
|
163
163
|
3. Add the page content to `src/data/site-data.json`.
|
|
164
164
|
|
|
165
|
+
### One-page section navigation
|
|
166
|
+
|
|
167
|
+
Use route links such as `/about` only when that route is exported. For a
|
|
168
|
+
one-page design, link to a stable section ID instead:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<a href="#about">About</a>
|
|
172
|
+
<section id="about" data-section-id="about" data-design-section="about">
|
|
173
|
+
{/* About content */}
|
|
174
|
+
</section>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Every visible navigation item must resolve to exactly one visible section in
|
|
178
|
+
the exported Home document. Keep labels such as Home, About, Services, Gallery,
|
|
179
|
+
and Contact as neutral template UI copy rather than AI-generated marketing
|
|
180
|
+
text. Test direct `/#about` loading and sticky-header scrolling before
|
|
181
|
+
packaging.
|
|
182
|
+
|
|
165
183
|
---
|
|
166
184
|
|
|
167
185
|
## Packaging for Fivora
|
|
@@ -347,6 +347,21 @@
|
|
|
347
347
|
"type": "text",
|
|
348
348
|
"label": "Feature"
|
|
349
349
|
}
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"key": "price",
|
|
353
|
+
"type": "number",
|
|
354
|
+
"label": "Price"
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
"key": "priceLabel",
|
|
358
|
+
"type": "text",
|
|
359
|
+
"label": "Price Label (e.g. Starting from, per hour)"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"key": "showPrice",
|
|
363
|
+
"type": "boolean",
|
|
364
|
+
"label": "Show Price on Storefront"
|
|
350
365
|
}
|
|
351
366
|
]
|
|
352
367
|
},
|
|
@@ -442,8 +457,7 @@
|
|
|
442
457
|
{
|
|
443
458
|
"key": "price",
|
|
444
459
|
"type": "number",
|
|
445
|
-
"label": "Price"
|
|
446
|
-
"required": true
|
|
460
|
+
"label": "Price"
|
|
447
461
|
},
|
|
448
462
|
{
|
|
449
463
|
"key": "compareAtPrice",
|
|
@@ -469,6 +483,31 @@
|
|
|
469
483
|
"key": "badge",
|
|
470
484
|
"type": "text",
|
|
471
485
|
"label": "Badge"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"key": "showPrice",
|
|
489
|
+
"type": "boolean",
|
|
490
|
+
"label": "Show Price on Storefront"
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"key": "isPriceRange",
|
|
494
|
+
"type": "boolean",
|
|
495
|
+
"label": "Enable Price Range"
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
"key": "minPrice",
|
|
499
|
+
"type": "number",
|
|
500
|
+
"label": "Minimum Price"
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"key": "maxPrice",
|
|
504
|
+
"type": "number",
|
|
505
|
+
"label": "Maximum Price"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"key": "priceRange",
|
|
509
|
+
"type": "text",
|
|
510
|
+
"label": "Price Range Display"
|
|
472
511
|
}
|
|
473
512
|
]
|
|
474
513
|
}
|
package/template/package.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"next": "15.5.23",
|
|
19
19
|
"react": "19.2.8",
|
|
20
20
|
"react-dom": "19.2.8",
|
|
21
|
-
"@deneb-ui/ui": "^2.0.
|
|
21
|
+
"@deneb-ui/ui": "^2.0.109"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@eslint/eslintrc": "3.3.6",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"eslint": "9.39.5",
|
|
29
29
|
"eslint-config-next": "15.5.23",
|
|
30
30
|
"typescript": "5.8.3",
|
|
31
|
-
"@deneb-ui/cli": "^2.0.
|
|
31
|
+
"@deneb-ui/cli": "^2.0.109",
|
|
32
32
|
"tailwindcss": "^3.4.17",
|
|
33
33
|
"postcss": "8.5.26",
|
|
34
34
|
"autoprefixer": "^10.4.20"
|
|
@@ -255,6 +255,28 @@ export default function HomePage() {
|
|
|
255
255
|
const badge = contentText(product.badge);
|
|
256
256
|
const category = contentText(product.category);
|
|
257
257
|
|
|
258
|
+
const itemShowPrice =
|
|
259
|
+
(product as any)?.showPrice !== undefined
|
|
260
|
+
? Boolean((product as any).showPrice)
|
|
261
|
+
: ((product as any)?.customData?.showPrice !== undefined
|
|
262
|
+
? Boolean((product as any).customData.showPrice)
|
|
263
|
+
: true);
|
|
264
|
+
const isRange = Boolean(
|
|
265
|
+
(product as any)?.isPriceRange ||
|
|
266
|
+
((product as any)?.minPrice !== undefined && (product as any)?.maxPrice !== undefined) ||
|
|
267
|
+
(product as any)?.priceRange
|
|
268
|
+
);
|
|
269
|
+
let displayPrice = `${currency} ${price}`;
|
|
270
|
+
if (isRange) {
|
|
271
|
+
if ((product as any).priceRange) {
|
|
272
|
+
displayPrice = String((product as any).priceRange);
|
|
273
|
+
} else {
|
|
274
|
+
const min = (product as any).minPrice !== undefined ? (product as any).minPrice : price;
|
|
275
|
+
const max = (product as any).maxPrice !== undefined ? (product as any).maxPrice : price;
|
|
276
|
+
displayPrice = `${currency} ${min} – ${currency} ${max}`;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
258
280
|
return (
|
|
259
281
|
<EditableCard
|
|
260
282
|
key={productId ?? index}
|
|
@@ -266,7 +288,11 @@ export default function HomePage() {
|
|
|
266
288
|
radius="xl"
|
|
267
289
|
style={{ display: 'flex', flexDirection: 'column' }}
|
|
268
290
|
>
|
|
269
|
-
<
|
|
291
|
+
<a
|
|
292
|
+
href={platformProductDetailHref(productId)}
|
|
293
|
+
data-preview-static="Open the stable live product detail page"
|
|
294
|
+
style={{ position: 'relative', overflow: 'hidden', borderRadius: '12px', marginBottom: '0.75rem', display: 'block' }}
|
|
295
|
+
>
|
|
270
296
|
<EditableImage
|
|
271
297
|
src={contentText(product.imageUrl) || '/placeholder.svg'}
|
|
272
298
|
alt={contentText(product.name)}
|
|
@@ -284,7 +310,7 @@ export default function HomePage() {
|
|
|
284
310
|
{badge}
|
|
285
311
|
</span>
|
|
286
312
|
)}
|
|
287
|
-
</
|
|
313
|
+
</a>
|
|
288
314
|
|
|
289
315
|
<div style={{ display: 'flex', flexDirection: 'column', flex: 1, gap: '0.5rem' }}>
|
|
290
316
|
{category && (
|
|
@@ -296,14 +322,20 @@ export default function HomePage() {
|
|
|
296
322
|
{category}
|
|
297
323
|
</span>
|
|
298
324
|
)}
|
|
299
|
-
<
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
325
|
+
<a
|
|
326
|
+
href={platformProductDetailHref(productId)}
|
|
327
|
+
data-preview-static="Open the stable live product detail page"
|
|
328
|
+
style={{ textDecoration: 'none', color: 'inherit' }}
|
|
329
|
+
>
|
|
330
|
+
<EditableText
|
|
331
|
+
variant="h3"
|
|
332
|
+
size="lg"
|
|
333
|
+
weight="bold"
|
|
334
|
+
color="heading"
|
|
335
|
+
data-preview-field-path={`products[${index}].name`}
|
|
336
|
+
defaultValue={contentText(product.name)}
|
|
337
|
+
/>
|
|
338
|
+
</a>
|
|
307
339
|
<EditableText
|
|
308
340
|
variant="p"
|
|
309
341
|
color="muted"
|
|
@@ -311,25 +343,45 @@ export default function HomePage() {
|
|
|
311
343
|
defaultValue={contentText(product.description)}
|
|
312
344
|
/>
|
|
313
345
|
|
|
314
|
-
|
|
315
|
-
<
|
|
316
|
-
as="span"
|
|
317
|
-
weight="bold"
|
|
318
|
-
size="xl"
|
|
319
|
-
color="primary"
|
|
320
|
-
data-preview-field-path={`products[${index}].price`}
|
|
321
|
-
defaultValue={`${currency} ${price}`}
|
|
322
|
-
/>
|
|
323
|
-
{compareAt > 0 && (
|
|
346
|
+
{itemShowPrice ? (
|
|
347
|
+
<div style={{ display: 'flex', alignItems: 'baseline', gap: '0.5rem', marginTop: 'auto', paddingTop: '0.75rem', flexWrap: 'wrap' }}>
|
|
324
348
|
<EditableText
|
|
325
349
|
as="span"
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
350
|
+
weight="bold"
|
|
351
|
+
size="xl"
|
|
352
|
+
color="primary"
|
|
353
|
+
data-preview-field-path={`products[${index}].price`}
|
|
354
|
+
defaultValue={displayPrice}
|
|
330
355
|
/>
|
|
331
|
-
|
|
332
|
-
|
|
356
|
+
{compareAt > 0 && !isRange && (
|
|
357
|
+
<EditableText
|
|
358
|
+
as="span"
|
|
359
|
+
color="muted"
|
|
360
|
+
style={{ textDecoration: 'line-through', fontSize: '0.875rem' }}
|
|
361
|
+
data-preview-field-path={`products[${index}].compareAtPrice`}
|
|
362
|
+
defaultValue={`${currency} ${compareAt}`}
|
|
363
|
+
/>
|
|
364
|
+
)}
|
|
365
|
+
</div>
|
|
366
|
+
) : (
|
|
367
|
+
<div style={{ marginTop: 'auto', paddingTop: '0.75rem' }}>
|
|
368
|
+
<span
|
|
369
|
+
style={{
|
|
370
|
+
display: 'inline-flex',
|
|
371
|
+
alignItems: 'center',
|
|
372
|
+
padding: '3px 8px',
|
|
373
|
+
borderRadius: '6px',
|
|
374
|
+
fontSize: '0.75rem',
|
|
375
|
+
fontWeight: 600,
|
|
376
|
+
backgroundColor: 'rgba(255, 255, 255, 0.08)',
|
|
377
|
+
color: 'var(--muted-text, #94a3b8)',
|
|
378
|
+
border: '1px solid rgba(255, 255, 255, 0.12)',
|
|
379
|
+
}}
|
|
380
|
+
>
|
|
381
|
+
Price on Request
|
|
382
|
+
</span>
|
|
383
|
+
</div>
|
|
384
|
+
)}
|
|
333
385
|
|
|
334
386
|
<div style={{ marginTop: '0.75rem' }}>
|
|
335
387
|
<a
|
|
@@ -93,6 +93,72 @@ export default function ServicesPage() {
|
|
|
93
93
|
))}
|
|
94
94
|
</ul>
|
|
95
95
|
)}
|
|
96
|
+
{(() => {
|
|
97
|
+
const itemShowPrice =
|
|
98
|
+
(service as any)?.showPrice !== undefined
|
|
99
|
+
? Boolean((service as any).showPrice)
|
|
100
|
+
: ((service as any)?.customData?.showPrice !== undefined
|
|
101
|
+
? Boolean((service as any).customData.showPrice)
|
|
102
|
+
: true);
|
|
103
|
+
const price = (service as any).price;
|
|
104
|
+
const priceLabel = contentText((service as any).priceLabel);
|
|
105
|
+
const hasNumericPrice = price !== undefined && price !== null && String(price).trim() !== '';
|
|
106
|
+
const formattedPrice = hasNumericPrice
|
|
107
|
+
? typeof price === 'number'
|
|
108
|
+
? `LKR ${price.toLocaleString()}`
|
|
109
|
+
: String(price).includes('LKR')
|
|
110
|
+
? String(price)
|
|
111
|
+
: `LKR ${price}`
|
|
112
|
+
: '';
|
|
113
|
+
|
|
114
|
+
if (itemShowPrice && (hasNumericPrice || priceLabel)) {
|
|
115
|
+
return (
|
|
116
|
+
<div style={{ marginTop: 'auto', paddingTop: '0.75rem', display: 'flex', alignItems: 'baseline', gap: '0.375rem', flexWrap: 'wrap' }}>
|
|
117
|
+
{hasNumericPrice && (
|
|
118
|
+
<EditableText
|
|
119
|
+
as="span"
|
|
120
|
+
weight="bold"
|
|
121
|
+
size="lg"
|
|
122
|
+
color="primary"
|
|
123
|
+
data-preview-field-path={`services[${index}].price`}
|
|
124
|
+
defaultValue={formattedPrice}
|
|
125
|
+
/>
|
|
126
|
+
)}
|
|
127
|
+
{priceLabel && (
|
|
128
|
+
<EditableText
|
|
129
|
+
as="span"
|
|
130
|
+
color="muted"
|
|
131
|
+
data-preview-field-path={`services[${index}].priceLabel`}
|
|
132
|
+
defaultValue={priceLabel}
|
|
133
|
+
style={{ fontSize: '0.8125rem' }}
|
|
134
|
+
/>
|
|
135
|
+
)}
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (!itemShowPrice) {
|
|
140
|
+
return (
|
|
141
|
+
<div style={{ marginTop: 'auto', paddingTop: '0.75rem' }}>
|
|
142
|
+
<span
|
|
143
|
+
style={{
|
|
144
|
+
display: 'inline-flex',
|
|
145
|
+
alignItems: 'center',
|
|
146
|
+
padding: '3px 8px',
|
|
147
|
+
borderRadius: '6px',
|
|
148
|
+
fontSize: '0.75rem',
|
|
149
|
+
fontWeight: 600,
|
|
150
|
+
backgroundColor: 'rgba(255, 255, 255, 0.08)',
|
|
151
|
+
color: 'var(--muted-text, #94a3b8)',
|
|
152
|
+
border: '1px solid rgba(255, 255, 255, 0.12)',
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
Quote on Request
|
|
156
|
+
</span>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
})()}
|
|
96
162
|
</EditableCard>
|
|
97
163
|
);
|
|
98
164
|
})}
|