veleta-templates 0.0.1 → 0.0.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.
Files changed (83) hide show
  1. package/dist/cjs/index-rvPH40G4.js +2 -6
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/veleta-boston-template.cjs.entry.js +116 -0
  4. package/dist/cjs/veleta-templates.cjs.js +1 -1
  5. package/dist/collection/collection-manifest.json +1 -2
  6. package/dist/collection/components/boston-template/boston-template.js +81 -0
  7. package/dist/collection/components/boston-template/boston-template.js.map +1 -0
  8. package/dist/collection/components.js +1 -2
  9. package/dist/collection/components.js.map +1 -1
  10. package/dist/collection/types/interfaces.js.map +1 -1
  11. package/dist/collection/utils/data-helpers.js +0 -8
  12. package/dist/collection/utils/data-helpers.js.map +1 -1
  13. package/dist/components/veleta-boston-template.d.ts +11 -0
  14. package/dist/components/veleta-boston-template.js +138 -0
  15. package/dist/components/veleta-boston-template.js.map +1 -0
  16. package/dist/esm/index-zOTWMTLj.js +2 -6
  17. package/dist/esm/loader.js +1 -1
  18. package/dist/esm/veleta-boston-template.entry.js +114 -0
  19. package/dist/esm/veleta-boston-template.entry.js.map +1 -0
  20. package/dist/esm/veleta-templates.js +1 -1
  21. package/dist/esm-es5/index-zOTWMTLj.js +1 -1
  22. package/dist/esm-es5/loader.js +1 -1
  23. package/dist/esm-es5/veleta-boston-template.entry.js +2 -0
  24. package/dist/esm-es5/veleta-boston-template.entry.js.map +1 -0
  25. package/dist/esm-es5/veleta-templates.js +1 -1
  26. package/dist/types/components/boston-template/boston-template.d.ts +7 -0
  27. package/dist/types/components.d.ts +11 -82
  28. package/dist/types/types/interfaces.d.ts +46 -20
  29. package/dist/types/utils/data-helpers.d.ts +0 -5
  30. package/dist/veleta-templates/p-23aa6aa2.entry.js +2 -0
  31. package/dist/veleta-templates/p-23aa6aa2.entry.js.map +1 -0
  32. package/dist/veleta-templates/p-83a66176.system.entry.js +2 -0
  33. package/dist/veleta-templates/p-83a66176.system.entry.js.map +1 -0
  34. package/dist/veleta-templates/p-D1BkLoGd.system.js +1 -1
  35. package/dist/veleta-templates/veleta-templates.esm.js +1 -1
  36. package/package.json +2 -2
  37. package/dist/cjs/prop-parser-CqlyGycg.js +0 -129
  38. package/dist/cjs/prop-parser-CqlyGycg.js.map +0 -1
  39. package/dist/cjs/veleta-demo-template.cjs.entry.js +0 -39
  40. package/dist/cjs/veleta-menu-template-b.cjs.entry.js +0 -60
  41. package/dist/collection/components/demo-template/demo-template.css +0 -57
  42. package/dist/collection/components/demo-template/demo-template.js +0 -144
  43. package/dist/collection/components/demo-template/demo-template.js.map +0 -1
  44. package/dist/collection/components/menu-template-b/menu-template-b.js +0 -150
  45. package/dist/collection/components/menu-template-b/menu-template-b.js.map +0 -1
  46. package/dist/collection/utils/mock-data.js +0 -85
  47. package/dist/collection/utils/mock-data.js.map +0 -1
  48. package/dist/components/p-BtFpp-ge.js +0 -124
  49. package/dist/components/p-BtFpp-ge.js.map +0 -1
  50. package/dist/components/veleta-demo-template.d.ts +0 -11
  51. package/dist/components/veleta-demo-template.js +0 -64
  52. package/dist/components/veleta-demo-template.js.map +0 -1
  53. package/dist/components/veleta-menu-template-b.d.ts +0 -11
  54. package/dist/components/veleta-menu-template-b.js +0 -85
  55. package/dist/components/veleta-menu-template-b.js.map +0 -1
  56. package/dist/esm/prop-parser-D5qpnUIY.js +0 -124
  57. package/dist/esm/prop-parser-D5qpnUIY.js.map +0 -1
  58. package/dist/esm/veleta-demo-template.entry.js +0 -37
  59. package/dist/esm/veleta-demo-template.entry.js.map +0 -1
  60. package/dist/esm/veleta-menu-template-b.entry.js +0 -58
  61. package/dist/esm/veleta-menu-template-b.entry.js.map +0 -1
  62. package/dist/esm-es5/prop-parser-D5qpnUIY.js +0 -2
  63. package/dist/esm-es5/prop-parser-D5qpnUIY.js.map +0 -1
  64. package/dist/esm-es5/veleta-demo-template.entry.js +0 -2
  65. package/dist/esm-es5/veleta-demo-template.entry.js.map +0 -1
  66. package/dist/esm-es5/veleta-menu-template-b.entry.js +0 -2
  67. package/dist/esm-es5/veleta-menu-template-b.entry.js.map +0 -1
  68. package/dist/types/components/demo-template/demo-template.d.ts +0 -12
  69. package/dist/types/components/menu-template-b/menu-template-b.d.ts +0 -11
  70. package/dist/types/utils/mock-data.d.ts +0 -9
  71. package/dist/veleta-templates/p-1da2f609.entry.js +0 -2
  72. package/dist/veleta-templates/p-1da2f609.entry.js.map +0 -1
  73. package/dist/veleta-templates/p-6f14da26.system.entry.js +0 -2
  74. package/dist/veleta-templates/p-6f14da26.system.entry.js.map +0 -1
  75. package/dist/veleta-templates/p-9e099798.entry.js +0 -2
  76. package/dist/veleta-templates/p-9e099798.entry.js.map +0 -1
  77. package/dist/veleta-templates/p-BtFpp-ge.js +0 -2
  78. package/dist/veleta-templates/p-BtFpp-ge.js.map +0 -1
  79. package/dist/veleta-templates/p-bbAxcnzz.system.js +0 -2
  80. package/dist/veleta-templates/p-bbAxcnzz.system.js.map +0 -1
  81. package/dist/veleta-templates/p-e7ecc57b.system.entry.js +0 -2
  82. package/dist/veleta-templates/p-e7ecc57b.system.entry.js.map +0 -1
  83. /package/dist/collection/components/{menu-template-b/menu-template-b.css → boston-template/boston-template.css} +0 -0
@@ -119,14 +119,10 @@ var loadModule = (cmpMeta, hostRef, hmrVersionId) => {
119
119
  }
120
120
  switch(bundleId) {
121
121
 
122
- case 'veleta-demo-template.cjs':
122
+ case 'veleta-boston-template.cjs':
123
123
  return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(
124
124
  /* webpackMode: "lazy" */
125
- './veleta-demo-template.cjs.entry.js')); }).then(processMod, consoleError);
126
- case 'veleta-menu-template-b.cjs':
127
- return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(
128
- /* webpackMode: "lazy" */
129
- './veleta-menu-template-b.cjs.entry.js')); }).then(processMod, consoleError);
125
+ './veleta-boston-template.cjs.entry.js')); }).then(processMod, consoleError);
130
126
  }
131
127
  }
132
128
  return (function (t) { return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(t)); }); })(
@@ -6,7 +6,7 @@ var appGlobals = require('./app-globals-V2Kpy_OQ.js');
6
6
  const defineCustomElements = async (win, options) => {
7
7
  if (typeof window === 'undefined') return undefined;
8
8
  await appGlobals.globalScripts();
9
- return index.bootstrapLazy([["veleta-demo-template.cjs",[[256,"veleta-demo-template",{"sectionsJson":[1,"sections-json"],"dishesJson":[1,"dishes-json"],"themeJson":[1,"theme-json"],"restaurantName":[1,"restaurant-name"]}]]],["veleta-menu-template-b.cjs",[[256,"veleta-menu-template-b",{"sectionsJson":[1,"sections-json"],"dishesJson":[1,"dishes-json"],"themeJson":[1,"theme-json"],"restaurantName":[1,"restaurant-name"]}]]]], options);
9
+ return index.bootstrapLazy([["veleta-boston-template.cjs",[[256,"veleta-boston-template",{"dataJson":[1,"data-json"]}]]]], options);
10
10
  };
11
11
 
12
12
  exports.setNonce = index.setNonce;
@@ -0,0 +1,116 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-rvPH40G4.js');
4
+
5
+ /**
6
+ * Carga fuentes usando webfontloader de forma dinámica.
7
+ * Esta función carga el módulo webfontloader solo cuando es necesario.
8
+ *
9
+ * @param fontConfig Configuración de fuentes para webfontloader
10
+ * @returns Promise que se resuelve cuando las fuentes se cargan
11
+ */
12
+ async function loadFonts(fontConfig) {
13
+ if (!fontConfig || (!fontConfig.google && !fontConfig.custom)) {
14
+ return Promise.resolve();
15
+ }
16
+ try {
17
+ // Importación dinámica de webfontloader
18
+ // webfontloader puede exportar de diferentes formas según el entorno
19
+ const webfontloaderModule = await Promise.resolve().then(function () { return require('./webfontloader-CDgRDOZ3.js'); }).then(function (n) { return n.webfontloader; });
20
+ const WebFont = webfontloaderModule.default || webfontloaderModule;
21
+ if (!WebFont || typeof WebFont.load !== 'function') {
22
+ console.warn('webfontloader no está disponible o no tiene el método load');
23
+ return Promise.resolve();
24
+ }
25
+ return new Promise((resolve) => {
26
+ const config = Object.assign(Object.assign({}, fontConfig), { active: () => {
27
+ if (fontConfig.active) {
28
+ fontConfig.active();
29
+ }
30
+ resolve();
31
+ }, inactive: () => {
32
+ if (fontConfig.inactive) {
33
+ fontConfig.inactive();
34
+ }
35
+ // No rechazamos la promesa, solo resolvemos
36
+ // para que el template pueda renderizarse con fuentes por defecto
37
+ resolve();
38
+ } });
39
+ WebFont.load(config);
40
+ });
41
+ }
42
+ catch (error) {
43
+ console.error('Error loading webfontloader:', error);
44
+ // Resolvemos en lugar de rechazar para que el template pueda renderizarse
45
+ return Promise.resolve();
46
+ }
47
+ }
48
+ /**
49
+ * Aplica la familia de fuente al elemento raíz del componente.
50
+ *
51
+ * @param element Elemento HTML al que aplicar la fuente
52
+ * @param fontFamily Familia de fuente CSS (ej: "Roboto, sans-serif")
53
+ */
54
+ function applyFontFamily(element, fontFamily) {
55
+ if (element) {
56
+ element.style.fontFamily = fontFamily;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Formatea un precio como string con símbolo de euro.
62
+ * Si es un número entero, no muestra decimales.
63
+ */
64
+ function formatPrice(price) {
65
+ return (price % 1 === 0 ? price.toString() : price.toFixed(2)) + '€';
66
+ }
67
+
68
+ const bostonTemplateCss = () => `.menu-wrapper{min-height:100vh;width:100%;padding:1.5rem 1rem;font-family:'Merriweather', serif;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;display:block}.menu-wrapper *,.menu-wrapper *::before,.menu-wrapper *::after{-webkit-box-sizing:border-box;box-sizing:border-box}.menu-wrapper h1,.menu-wrapper h2,.menu-wrapper h3,.menu-wrapper h4,.menu-wrapper h5,.menu-wrapper h6,.menu-wrapper p,.menu-wrapper ul,.menu-wrapper ol,.menu-wrapper li,.menu-wrapper header,.menu-wrapper section,.menu-wrapper article,.menu-wrapper aside,.menu-wrapper nav,.menu-wrapper blockquote,.menu-wrapper figure,.menu-wrapper figcaption{margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}.menu-wrapper ul,.menu-wrapper ol{padding:0}@media (min-width: 640px){.menu-wrapper{padding:2rem 1.5rem}}@media (min-width: 768px){.menu-wrapper{padding:2rem 1rem}}.menu-container{max-width:1280px;margin:0 auto}.menu-header{text-align:center}@media (min-width: 768px){.menu-header{margin-bottom:3rem}}.restaurant-title{font-size:2rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;line-height:1.1;margin:0 0 1.5rem 0!important}@media (min-width: 640px){.restaurant-title{font-size:2.5rem;margin:0 0 3rem 0!important}}@media (min-width: 768px){.restaurant-title{font-size:3rem}}@media (min-width: 1024px){.restaurant-title{font-size:3.5rem}}.sections-container{display:grid;grid-template-columns:1fr;gap:3rem}@media (min-width: 768px){.sections-container{grid-template-columns:repeat(2, 1fr);gap:4rem}}.menu-section{display:-ms-flexbox;display:flex;width:100%;position:relative}.section-label-wrapper{position:relative;width:3rem;-ms-flex-negative:0;flex-shrink:0;margin-right:1rem;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end}.section-label-line{position:absolute;right:0;top:0;bottom:0;width:1px;border-right:1px solid}.section-label{font-weight:700;font-size:1.125rem;text-transform:uppercase;letter-spacing:0.15em;-webkit-writing-mode:vertical-rl;-ms-writing-mode:tb-rl;writing-mode:vertical-rl;-webkit-transform:rotate(180deg);transform:rotate(180deg);text-align:right;white-space:nowrap;margin:0 0 0.5rem 0;-webkit-margin-after:0.5rem;margin-block-end:0.5rem;position:absolute;top:0}@media (min-width: 640px){.section-label{font-size:1.2375rem}}@media (min-width: 768px){.section-label{font-size:1.35rem}}@media (min-width: 1024px){.section-label{font-size:1.51875rem}}.section-content{-ms-flex:1;flex:1;padding-top:0.25rem}.section-description{font-size:0.875rem;font-style:italic;margin:0 0 1rem 0!important;-webkit-margin-after:1rem;margin-block-end:1rem;opacity:0.75;color:inherit}@media (min-width: 640px){.section-description{font-size:0.9625rem}}@media (min-width: 768px){.section-description{font-size:1.05rem}}@media (min-width: 1024px){.section-description{font-size:1.18125rem}}.dishes-list{list-style:none;padding:0;margin:0;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;gap:1rem}.dish-item{position:relative}.dish-header{display:-ms-flexbox;display:flex;-ms-flex-align:baseline;align-items:baseline;width:100%;gap:0.5rem}.dish-name{font-size:1rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;-ms-flex-negative:0;flex-shrink:0}@media (min-width: 640px){.dish-name{font-size:1.1rem}}@media (min-width: 768px){.dish-name{font-size:1.2rem}}@media (min-width: 1024px){.dish-name{font-size:1.35rem}}.dish-dots{-ms-flex:1;flex:1;opacity:0.25;border-bottom:1px dotted;margin:0 0.55rem;position:relative;top:-5px;border-color:currentColor}.dish-price{font-size:1rem;font-weight:700;-ms-flex-negative:0;flex-shrink:0;text-align:right}@media (min-width: 640px){.dish-price{font-size:1.1rem}}@media (min-width: 768px){.dish-price{font-size:1.2rem}}@media (min-width: 1024px){.dish-price{font-size:1.35rem}}.dish-description{font-size:0.8125rem;margin-top:-0.9rem;line-height:1.4;opacity:0.7;color:inherit}@media (min-width: 640px){.dish-description{font-size:0.9425rem}}`;
69
+
70
+ const BostonTemplate = class {
71
+ constructor(hostRef) {
72
+ index.registerInstance(this, hostRef);
73
+ this.dataJson = '{}';
74
+ this.fontConfig = {
75
+ google: {
76
+ families: ['Oswald:400,600,700', 'Merriweather:300,400,700'],
77
+ },
78
+ };
79
+ }
80
+ async componentWillLoad() {
81
+ await loadFonts(this.fontConfig);
82
+ applyFontFamily(this.el, 'Merriweather, serif');
83
+ }
84
+ render() {
85
+ var _a;
86
+ let menuData = null;
87
+ try {
88
+ menuData = JSON.parse(this.dataJson);
89
+ }
90
+ catch (e) {
91
+ console.warn('Invalid dataJson provided to veleta-boston-template');
92
+ }
93
+ const theme = (_a = menuData === null || menuData === void 0 ? void 0 : menuData.templateData) === null || _a === void 0 ? void 0 : _a.theme;
94
+ const primary = (theme === null || theme === void 0 ? void 0 : theme.primaryColor) || '#1a365d';
95
+ const fontBody = 'Merriweather, serif';
96
+ const fontTitle = 'Oswald, sans-serif';
97
+ if (!menuData) {
98
+ return index.h("div", { class: "menu-wrapper", style: { color: primary } });
99
+ }
100
+ const { sections, business } = menuData;
101
+ // Ordenar secciones por 'order'
102
+ const sortedSections = (sections || []).sort((a, b) => a.order - b.order);
103
+ return (index.h("div", { class: "menu-wrapper", style: { color: primary } }, index.h("div", { class: "menu-container" }, (business === null || business === void 0 ? void 0 : business.name) && (index.h("header", { class: "menu-header" }, index.h("h1", { class: "restaurant-title", style: { fontFamily: fontTitle } }, business.name))), index.h("div", { class: "sections-container" }, sortedSections.map(section => {
104
+ // Ordenar platos por 'order'
105
+ const sectionDishes = (section.dishes || []).sort((a, b) => a.order - b.order);
106
+ if (!sectionDishes.length)
107
+ return null;
108
+ return (index.h("section", { key: section.id, class: "menu-section" }, index.h("div", { class: "section-label-wrapper" }, index.h("div", { class: "section-label-line", style: { borderColor: primary } }), index.h("h2", { class: "section-label", style: { fontFamily: fontTitle, color: primary } }, section.title)), index.h("div", { class: "section-content" }, section.description && (index.h("p", { class: "section-description", style: { fontFamily: fontBody } }, section.description)), index.h("ul", { class: "dishes-list" }, sectionDishes.map(dish => (index.h("li", { key: dish.id, class: "dish-item" }, index.h("div", { class: "dish-header" }, index.h("h3", { class: "dish-name", style: { fontFamily: fontTitle, color: primary } }, dish.name), index.h("div", { class: "dish-dots" }), index.h("span", { class: "dish-price", style: { fontFamily: fontTitle, color: primary } }, formatPrice(dish.price))), dish.description && (index.h("p", { class: "dish-description", style: { fontFamily: fontBody } }, dish.description)))))))));
109
+ })))));
110
+ }
111
+ get el() { return index.getElement(this); }
112
+ };
113
+ BostonTemplate.style = bostonTemplateCss();
114
+
115
+ exports.veleta_boston_template = BostonTemplate;
116
+ //# sourceMappingURL=veleta-boston-template.entry.cjs.js.map
@@ -19,7 +19,7 @@ var patchBrowser = () => {
19
19
 
20
20
  patchBrowser().then(async (options) => {
21
21
  await appGlobals.globalScripts();
22
- return index.bootstrapLazy([["veleta-demo-template.cjs",[[256,"veleta-demo-template",{"sectionsJson":[1,"sections-json"],"dishesJson":[1,"dishes-json"],"themeJson":[1,"theme-json"],"restaurantName":[1,"restaurant-name"]}]]],["veleta-menu-template-b.cjs",[[256,"veleta-menu-template-b",{"sectionsJson":[1,"sections-json"],"dishesJson":[1,"dishes-json"],"themeJson":[1,"theme-json"],"restaurantName":[1,"restaurant-name"]}]]]], options);
22
+ return index.bootstrapLazy([["veleta-boston-template.cjs",[[256,"veleta-boston-template",{"dataJson":[1,"data-json"]}]]]], options);
23
23
  });
24
24
 
25
25
  exports.setNonce = index.setNonce;
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "entries": [
3
- "components/demo-template/demo-template.js",
4
- "components/menu-template-b/menu-template-b.js"
3
+ "components/boston-template/boston-template.js"
5
4
  ],
6
5
  "compiler": {
7
6
  "name": "@stencil/core",
@@ -0,0 +1,81 @@
1
+ import { h } from "@stencil/core";
2
+ import { loadFonts, applyFontFamily } from "../../utils/font-loader";
3
+ import { formatPrice } from "../../utils/data-helpers";
4
+ export class BostonTemplate {
5
+ constructor() {
6
+ this.dataJson = '{}';
7
+ this.fontConfig = {
8
+ google: {
9
+ families: ['Oswald:400,600,700', 'Merriweather:300,400,700'],
10
+ },
11
+ };
12
+ }
13
+ async componentWillLoad() {
14
+ await loadFonts(this.fontConfig);
15
+ applyFontFamily(this.el, 'Merriweather, serif');
16
+ }
17
+ render() {
18
+ var _a;
19
+ let menuData = null;
20
+ try {
21
+ menuData = JSON.parse(this.dataJson);
22
+ }
23
+ catch (e) {
24
+ console.warn('Invalid dataJson provided to veleta-boston-template');
25
+ }
26
+ const theme = (_a = menuData === null || menuData === void 0 ? void 0 : menuData.templateData) === null || _a === void 0 ? void 0 : _a.theme;
27
+ const primary = (theme === null || theme === void 0 ? void 0 : theme.primaryColor) || '#1a365d';
28
+ const fontBody = 'Merriweather, serif';
29
+ const fontTitle = 'Oswald, sans-serif';
30
+ if (!menuData) {
31
+ return h("div", { class: "menu-wrapper", style: { color: primary } });
32
+ }
33
+ const { sections, business } = menuData;
34
+ // Ordenar secciones por 'order'
35
+ const sortedSections = (sections || []).sort((a, b) => a.order - b.order);
36
+ return (h("div", { class: "menu-wrapper", style: { color: primary } }, h("div", { class: "menu-container" }, (business === null || business === void 0 ? void 0 : business.name) && (h("header", { class: "menu-header" }, h("h1", { class: "restaurant-title", style: { fontFamily: fontTitle } }, business.name))), h("div", { class: "sections-container" }, sortedSections.map(section => {
37
+ // Ordenar platos por 'order'
38
+ const sectionDishes = (section.dishes || []).sort((a, b) => a.order - b.order);
39
+ if (!sectionDishes.length)
40
+ return null;
41
+ return (h("section", { key: section.id, class: "menu-section" }, h("div", { class: "section-label-wrapper" }, h("div", { class: "section-label-line", style: { borderColor: primary } }), h("h2", { class: "section-label", style: { fontFamily: fontTitle, color: primary } }, section.title)), h("div", { class: "section-content" }, section.description && (h("p", { class: "section-description", style: { fontFamily: fontBody } }, section.description)), h("ul", { class: "dishes-list" }, sectionDishes.map(dish => (h("li", { key: dish.id, class: "dish-item" }, h("div", { class: "dish-header" }, h("h3", { class: "dish-name", style: { fontFamily: fontTitle, color: primary } }, dish.name), h("div", { class: "dish-dots" }), h("span", { class: "dish-price", style: { fontFamily: fontTitle, color: primary } }, formatPrice(dish.price))), dish.description && (h("p", { class: "dish-description", style: { fontFamily: fontBody } }, dish.description)))))))));
42
+ })))));
43
+ }
44
+ static get is() { return "veleta-boston-template"; }
45
+ static get originalStyleUrls() {
46
+ return {
47
+ "$": ["boston-template.css"]
48
+ };
49
+ }
50
+ static get styleUrls() {
51
+ return {
52
+ "$": ["boston-template.css"]
53
+ };
54
+ }
55
+ static get properties() {
56
+ return {
57
+ "dataJson": {
58
+ "type": "string",
59
+ "mutable": false,
60
+ "complexType": {
61
+ "original": "string",
62
+ "resolved": "string",
63
+ "references": {}
64
+ },
65
+ "required": false,
66
+ "optional": false,
67
+ "docs": {
68
+ "tags": [],
69
+ "text": ""
70
+ },
71
+ "getter": false,
72
+ "setter": false,
73
+ "reflect": false,
74
+ "attribute": "data-json",
75
+ "defaultValue": "'{}'"
76
+ }
77
+ };
78
+ }
79
+ static get elementRef() { return "el"; }
80
+ }
81
+ //# sourceMappingURL=boston-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boston-template.js","sourceRoot":"","sources":["../../../src/components/boston-template/boston-template.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, h, Element } from '@stencil/core';\nimport { Menu } from '../../types/interfaces';\nimport { loadFonts, applyFontFamily } from '../../utils/font-loader';\nimport { formatPrice } from '../../utils/data-helpers';\n\n@Component({\n tag: 'veleta-boston-template',\n styleUrl: 'boston-template.css',\n shadow: false,\n})\nexport class BostonTemplate {\n @Element() el: HTMLElement;\n\n @Prop() dataJson: string = '{}';\n\n private readonly fontConfig = {\n google: {\n families: ['Oswald:400,600,700', 'Merriweather:300,400,700'],\n },\n };\n\n async componentWillLoad() {\n await loadFonts(this.fontConfig);\n applyFontFamily(this.el, 'Merriweather, serif');\n }\n\n render() {\n let menuData: Menu | null = null;\n try {\n menuData = JSON.parse(this.dataJson);\n } catch (e) {\n console.warn('Invalid dataJson provided to veleta-boston-template');\n }\n\n const theme = menuData?.templateData?.theme;\n const primary = theme?.primaryColor || '#1a365d';\n const fontBody = 'Merriweather, serif';\n const fontTitle = 'Oswald, sans-serif';\n\n if (!menuData) {\n return <div class=\"menu-wrapper\" style={{ color: primary }}></div>;\n }\n\n const { sections, business } = menuData;\n // Ordenar secciones por 'order'\n const sortedSections = (sections || []).sort((a, b) => a.order - b.order);\n\n return (\n <div\n class=\"menu-wrapper\"\n style={{ color: primary }}\n >\n <div class=\"menu-container\">\n {business?.name && (\n <header class=\"menu-header\">\n <h1 class=\"restaurant-title\" style={{ fontFamily: fontTitle }}>\n {business.name}\n </h1>\n </header>\n )}\n\n {/* Layout: 1 columna mobile, 2 columnas tablet/desktop */}\n <div class=\"sections-container\">\n {sortedSections.map(section => {\n // Ordenar platos por 'order'\n const sectionDishes = (section.dishes || []).sort((a, b) => a.order - b.order);\n if (!sectionDishes.length) return null;\n\n return (\n <section key={section.id} class=\"menu-section\">\n {/* Título vertical izquierdo */}\n <div class=\"section-label-wrapper\">\n <div class=\"section-label-line\" style={{ borderColor: primary }}></div>\n <h2\n class=\"section-label\"\n style={{ fontFamily: fontTitle, color: primary }}\n >\n {section.title}\n </h2>\n </div>\n\n {/* Contenido de platos */}\n <div class=\"section-content\">\n {section.description && (\n <p class=\"section-description\" style={{ fontFamily: fontBody }}>\n {section.description}\n </p>\n )}\n\n <ul class=\"dishes-list\">\n {sectionDishes.map(dish => (\n <li key={dish.id} class=\"dish-item\">\n <div class=\"dish-header\">\n <h3\n class=\"dish-name\"\n style={{ fontFamily: fontTitle, color: primary }}\n >\n {dish.name}\n </h3>\n <div\n class=\"dish-dots\"\n ></div>\n <span\n class=\"dish-price\"\n style={{ fontFamily: fontTitle, color: primary }}\n >\n {formatPrice(dish.price)}\n </span>\n </div>\n {dish.description && (\n <p class=\"dish-description\" style={{ fontFamily: fontBody }}>\n {dish.description}\n </p>\n )}\n </li>\n ))}\n </ul>\n </div>\n </section>\n );\n })}\n </div>\n </div>\n </div>\n );\n }\n}"]}
@@ -1,3 +1,2 @@
1
- export * from './components/demo-template/demo-template';
2
- export * from './components/menu-template-b/menu-template-b';
1
+ export * from './components/boston-template/boston-template';
3
2
  //# sourceMappingURL=components.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"AAAA,cAAc,0CAA0C,CAAC;AACzD,cAAc,8CAA8C,CAAC","sourcesContent":["export * from './components/demo-template/demo-template';\nexport * from './components/menu-template-b/menu-template-b';\n\n"]}
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"AAAA,cAAc,8CAA8C,CAAC","sourcesContent":["export * from './components/boston-template/boston-template';\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/types/interfaces.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Representa una sección del menú que agrupa platos.\n */\nexport interface Section {\n id: string; // Identificador único de la sección (requerido)\n title: string; // Título de la sección (requerido)\n description?: string; // Descripción opcional de la sección\n order: number; // Índice de orden para ordenar secciones (requerido)\n}\n\n/**\n * Representa un plato individual del menú que pertenece a una sección.\n */\nexport interface Dish {\n id: string; // Identificador único del plato (requerido)\n name: string; // Nombre del plato (requerido)\n price: number; // Precio del plato en euros (requerido, > 0)\n description?: string; // Descripción opcional del plato\n sectionId: string; // ID de la sección a la que pertenece (requerido)\n order: number; // Índice de orden dentro de la sección (requerido)\n}\n\n/**\n * Representa la configuración de colores del tema para el template.\n */\nexport interface Theme {\n id: string; // Identificador único del tema (requerido)\n name: string; // Nombre del tema (requerido)\n primaryColor: string; // Color primario en formato hexadecimal (requerido, ej: \"#3B82F6\")\n secondaryColor?: string | null; // Color secundario en formato hexadecimal (opcional, ej: \"#60A5FA\")\n backgroundColor?: string | null; // Color de fondo en formato hexadecimal (opcional, ej: \"#FFFFFF\")\n}\n\n/**\n * Propiedades que reciben los componentes Stencil como strings JSON.\n */\nexport interface TemplateProps {\n restaurantName: string; // Nombre del restaurante\n sectionsJson: string; // JSON string del array de secciones\n dishesJson: string; // JSON string del array de platos\n themeJson: string; // JSON string del objeto de tema\n}\n\n"]}
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/types/interfaces.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Representa un plato individual del menú.\n */\nexport interface Dish {\n id: string;\n name: string;\n price: number;\n available: boolean;\n order: number;\n description?: string;\n}\n\n/**\n * Representa la configuración de colores del tema para el template.\n */\nexport interface Theme {\n id: string;\n name: string;\n primaryColor: string;\n secondaryColor?: string | null;\n backgroundColor?: string | null;\n}\n\nexport interface MenuInfo {\n id: string;\n businessId: string;\n name: string;\n slug: string;\n active: boolean;\n}\n\nexport interface BusinessInfo {\n name: string;\n description: string;\n instagramUrl: string;\n}\n\nexport interface SectionWithDishes {\n id: string;\n title: string;\n order: number;\n description?: string;\n dishes: Dish[];\n}\n\nexport interface Config {\n id: string;\n template: string;\n themeId: string;\n createdAt: { seconds: number; nanoseconds: number };\n updatedAt: { seconds: number; nanoseconds: number };\n}\n\nexport interface TemplateData {\n id: string;\n name: string;\n theme: Theme;\n}\n\nexport interface Menu {\n menu: MenuInfo;\n sections: SectionWithDishes[];\n business: BusinessInfo;\n config: Config;\n templateData: TemplateData;\n}\n"]}
@@ -1,11 +1,3 @@
1
- /**
2
- * Obtiene los platos de una sección específica, ordenados por order.
3
- */
4
- export function getDishesBySection(sectionId, dishes) {
5
- return dishes
6
- .filter(d => d.sectionId === sectionId)
7
- .sort((a, b) => a.order - b.order);
8
- }
9
1
  /**
10
2
  * Formatea un precio como string con símbolo de euro.
11
3
  * Si es un número entero, no muestra decimales.
@@ -1 +1 @@
1
- {"version":3,"file":"data-helpers.js","sourceRoot":"","sources":["../../src/utils/data-helpers.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB,EAAE,MAAc;IAClE,OAAO,MAAM;SACV,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC;SACtC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACvE,CAAC","sourcesContent":["import { Dish } from '../types/interfaces';\n\n/**\n * Obtiene los platos de una sección específica, ordenados por order.\n */\nexport function getDishesBySection(sectionId: string, dishes: Dish[]): Dish[] {\n return dishes\n .filter(d => d.sectionId === sectionId)\n .sort((a, b) => a.order - b.order);\n}\n\n/**\n * Formatea un precio como string con símbolo de euro.\n * Si es un número entero, no muestra decimales.\n */\nexport function formatPrice(price: number): string {\n return (price % 1 === 0 ? price.toString() : price.toFixed(2)) + '€';\n}\n\n"]}
1
+ {"version":3,"file":"data-helpers.js","sourceRoot":"","sources":["../../src/utils/data-helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACvE,CAAC","sourcesContent":["/**\n * Formatea un precio como string con símbolo de euro.\n * Si es un número entero, no muestra decimales.\n */\nexport function formatPrice(price: number): string {\n return (price % 1 === 0 ? price.toString() : price.toFixed(2)) + '€';\n}\n\n\n\n"]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface VeletaBostonTemplate extends Components.VeletaBostonTemplate, HTMLElement {}
4
+ export const VeletaBostonTemplate: {
5
+ prototype: VeletaBostonTemplate;
6
+ new (): VeletaBostonTemplate;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,138 @@
1
+ import { t as transformTag, p as proxyCustomElement, H, h } from './index.js';
2
+
3
+ /**
4
+ * Carga fuentes usando webfontloader de forma dinámica.
5
+ * Esta función carga el módulo webfontloader solo cuando es necesario.
6
+ *
7
+ * @param fontConfig Configuración de fuentes para webfontloader
8
+ * @returns Promise que se resuelve cuando las fuentes se cargan
9
+ */
10
+ async function loadFonts(fontConfig) {
11
+ if (!fontConfig || (!fontConfig.google && !fontConfig.custom)) {
12
+ return Promise.resolve();
13
+ }
14
+ try {
15
+ // Importación dinámica de webfontloader
16
+ // webfontloader puede exportar de diferentes formas según el entorno
17
+ const webfontloaderModule = await import('./p-DjUJwx0S.js').then(function (n) { return n.w; });
18
+ const WebFont = webfontloaderModule.default || webfontloaderModule;
19
+ if (!WebFont || typeof WebFont.load !== 'function') {
20
+ console.warn('webfontloader no está disponible o no tiene el método load');
21
+ return Promise.resolve();
22
+ }
23
+ return new Promise((resolve) => {
24
+ const config = Object.assign(Object.assign({}, fontConfig), { active: () => {
25
+ if (fontConfig.active) {
26
+ fontConfig.active();
27
+ }
28
+ resolve();
29
+ }, inactive: () => {
30
+ if (fontConfig.inactive) {
31
+ fontConfig.inactive();
32
+ }
33
+ // No rechazamos la promesa, solo resolvemos
34
+ // para que el template pueda renderizarse con fuentes por defecto
35
+ resolve();
36
+ } });
37
+ WebFont.load(config);
38
+ });
39
+ }
40
+ catch (error) {
41
+ console.error('Error loading webfontloader:', error);
42
+ // Resolvemos en lugar de rechazar para que el template pueda renderizarse
43
+ return Promise.resolve();
44
+ }
45
+ }
46
+ /**
47
+ * Aplica la familia de fuente al elemento raíz del componente.
48
+ *
49
+ * @param element Elemento HTML al que aplicar la fuente
50
+ * @param fontFamily Familia de fuente CSS (ej: "Roboto, sans-serif")
51
+ */
52
+ function applyFontFamily(element, fontFamily) {
53
+ if (element) {
54
+ element.style.fontFamily = fontFamily;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Formatea un precio como string con símbolo de euro.
60
+ * Si es un número entero, no muestra decimales.
61
+ */
62
+ function formatPrice(price) {
63
+ return (price % 1 === 0 ? price.toString() : price.toFixed(2)) + '€';
64
+ }
65
+
66
+ const bostonTemplateCss = () => `.menu-wrapper{min-height:100vh;width:100%;padding:1.5rem 1rem;font-family:'Merriweather', serif;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;display:block}.menu-wrapper *,.menu-wrapper *::before,.menu-wrapper *::after{-webkit-box-sizing:border-box;box-sizing:border-box}.menu-wrapper h1,.menu-wrapper h2,.menu-wrapper h3,.menu-wrapper h4,.menu-wrapper h5,.menu-wrapper h6,.menu-wrapper p,.menu-wrapper ul,.menu-wrapper ol,.menu-wrapper li,.menu-wrapper header,.menu-wrapper section,.menu-wrapper article,.menu-wrapper aside,.menu-wrapper nav,.menu-wrapper blockquote,.menu-wrapper figure,.menu-wrapper figcaption{margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}.menu-wrapper ul,.menu-wrapper ol{padding:0}@media (min-width: 640px){.menu-wrapper{padding:2rem 1.5rem}}@media (min-width: 768px){.menu-wrapper{padding:2rem 1rem}}.menu-container{max-width:1280px;margin:0 auto}.menu-header{text-align:center}@media (min-width: 768px){.menu-header{margin-bottom:3rem}}.restaurant-title{font-size:2rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;line-height:1.1;margin:0 0 1.5rem 0!important}@media (min-width: 640px){.restaurant-title{font-size:2.5rem;margin:0 0 3rem 0!important}}@media (min-width: 768px){.restaurant-title{font-size:3rem}}@media (min-width: 1024px){.restaurant-title{font-size:3.5rem}}.sections-container{display:grid;grid-template-columns:1fr;gap:3rem}@media (min-width: 768px){.sections-container{grid-template-columns:repeat(2, 1fr);gap:4rem}}.menu-section{display:-ms-flexbox;display:flex;width:100%;position:relative}.section-label-wrapper{position:relative;width:3rem;-ms-flex-negative:0;flex-shrink:0;margin-right:1rem;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end}.section-label-line{position:absolute;right:0;top:0;bottom:0;width:1px;border-right:1px solid}.section-label{font-weight:700;font-size:1.125rem;text-transform:uppercase;letter-spacing:0.15em;-webkit-writing-mode:vertical-rl;-ms-writing-mode:tb-rl;writing-mode:vertical-rl;-webkit-transform:rotate(180deg);transform:rotate(180deg);text-align:right;white-space:nowrap;margin:0 0 0.5rem 0;-webkit-margin-after:0.5rem;margin-block-end:0.5rem;position:absolute;top:0}@media (min-width: 640px){.section-label{font-size:1.2375rem}}@media (min-width: 768px){.section-label{font-size:1.35rem}}@media (min-width: 1024px){.section-label{font-size:1.51875rem}}.section-content{-ms-flex:1;flex:1;padding-top:0.25rem}.section-description{font-size:0.875rem;font-style:italic;margin:0 0 1rem 0!important;-webkit-margin-after:1rem;margin-block-end:1rem;opacity:0.75;color:inherit}@media (min-width: 640px){.section-description{font-size:0.9625rem}}@media (min-width: 768px){.section-description{font-size:1.05rem}}@media (min-width: 1024px){.section-description{font-size:1.18125rem}}.dishes-list{list-style:none;padding:0;margin:0;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;gap:1rem}.dish-item{position:relative}.dish-header{display:-ms-flexbox;display:flex;-ms-flex-align:baseline;align-items:baseline;width:100%;gap:0.5rem}.dish-name{font-size:1rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;-ms-flex-negative:0;flex-shrink:0}@media (min-width: 640px){.dish-name{font-size:1.1rem}}@media (min-width: 768px){.dish-name{font-size:1.2rem}}@media (min-width: 1024px){.dish-name{font-size:1.35rem}}.dish-dots{-ms-flex:1;flex:1;opacity:0.25;border-bottom:1px dotted;margin:0 0.55rem;position:relative;top:-5px;border-color:currentColor}.dish-price{font-size:1rem;font-weight:700;-ms-flex-negative:0;flex-shrink:0;text-align:right}@media (min-width: 640px){.dish-price{font-size:1.1rem}}@media (min-width: 768px){.dish-price{font-size:1.2rem}}@media (min-width: 1024px){.dish-price{font-size:1.35rem}}.dish-description{font-size:0.8125rem;margin-top:-0.9rem;line-height:1.4;opacity:0.7;color:inherit}@media (min-width: 640px){.dish-description{font-size:0.9425rem}}`;
67
+
68
+ const BostonTemplate = /*@__PURE__*/ proxyCustomElement(class BostonTemplate extends H {
69
+ constructor(registerHost) {
70
+ super();
71
+ if (registerHost !== false) {
72
+ this.__registerHost();
73
+ }
74
+ this.dataJson = '{}';
75
+ this.fontConfig = {
76
+ google: {
77
+ families: ['Oswald:400,600,700', 'Merriweather:300,400,700'],
78
+ },
79
+ };
80
+ }
81
+ async componentWillLoad() {
82
+ await loadFonts(this.fontConfig);
83
+ applyFontFamily(this.el, 'Merriweather, serif');
84
+ }
85
+ render() {
86
+ var _a;
87
+ let menuData = null;
88
+ try {
89
+ menuData = JSON.parse(this.dataJson);
90
+ }
91
+ catch (e) {
92
+ console.warn('Invalid dataJson provided to veleta-boston-template');
93
+ }
94
+ const theme = (_a = menuData === null || menuData === void 0 ? void 0 : menuData.templateData) === null || _a === void 0 ? void 0 : _a.theme;
95
+ const primary = (theme === null || theme === void 0 ? void 0 : theme.primaryColor) || '#1a365d';
96
+ const fontBody = 'Merriweather, serif';
97
+ const fontTitle = 'Oswald, sans-serif';
98
+ if (!menuData) {
99
+ return h("div", { class: "menu-wrapper", style: { color: primary } });
100
+ }
101
+ const { sections, business } = menuData;
102
+ // Ordenar secciones por 'order'
103
+ const sortedSections = (sections || []).sort((a, b) => a.order - b.order);
104
+ return (h("div", { class: "menu-wrapper", style: { color: primary } }, h("div", { class: "menu-container" }, (business === null || business === void 0 ? void 0 : business.name) && (h("header", { class: "menu-header" }, h("h1", { class: "restaurant-title", style: { fontFamily: fontTitle } }, business.name))), h("div", { class: "sections-container" }, sortedSections.map(section => {
105
+ // Ordenar platos por 'order'
106
+ const sectionDishes = (section.dishes || []).sort((a, b) => a.order - b.order);
107
+ if (!sectionDishes.length)
108
+ return null;
109
+ return (h("section", { key: section.id, class: "menu-section" }, h("div", { class: "section-label-wrapper" }, h("div", { class: "section-label-line", style: { borderColor: primary } }), h("h2", { class: "section-label", style: { fontFamily: fontTitle, color: primary } }, section.title)), h("div", { class: "section-content" }, section.description && (h("p", { class: "section-description", style: { fontFamily: fontBody } }, section.description)), h("ul", { class: "dishes-list" }, sectionDishes.map(dish => (h("li", { key: dish.id, class: "dish-item" }, h("div", { class: "dish-header" }, h("h3", { class: "dish-name", style: { fontFamily: fontTitle, color: primary } }, dish.name), h("div", { class: "dish-dots" }), h("span", { class: "dish-price", style: { fontFamily: fontTitle, color: primary } }, formatPrice(dish.price))), dish.description && (h("p", { class: "dish-description", style: { fontFamily: fontBody } }, dish.description)))))))));
110
+ })))));
111
+ }
112
+ get el() { return this; }
113
+ static get style() { return bostonTemplateCss(); }
114
+ }, [256, "veleta-boston-template", {
115
+ "dataJson": [1, "data-json"]
116
+ }]);
117
+ function defineCustomElement$1() {
118
+ if (typeof customElements === "undefined") {
119
+ return;
120
+ }
121
+ const components = ["veleta-boston-template"];
122
+ components.forEach(tagName => { switch (tagName) {
123
+ case "veleta-boston-template":
124
+ if (!customElements.get(transformTag(tagName))) {
125
+ customElements.define(transformTag(tagName), BostonTemplate);
126
+ }
127
+ break;
128
+ } });
129
+ }
130
+ defineCustomElement$1();
131
+
132
+ const VeletaBostonTemplate = BostonTemplate;
133
+ const defineCustomElement = defineCustomElement$1;
134
+
135
+ export { VeletaBostonTemplate, defineCustomElement };
136
+ //# sourceMappingURL=veleta-boston-template.js.map
137
+
138
+ //# sourceMappingURL=veleta-boston-template.js.map
@@ -0,0 +1 @@
1
+ {"file":"veleta-boston-template.js","mappings":"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","names":["__stencil_proxyCustomElement","HTMLElement"],"sources":["src/utils/font-loader.ts","src/utils/data-helpers.ts","src/components/boston-template/boston-template.css?tag=veleta-boston-template","src/components/boston-template/boston-template.tsx"],"sourcesContent":["/**\n * Configuración de fuente para webfontloader.\n * Tipo local usado solo en este módulo.\n */\ninterface FontConfig {\n google?: {\n families: string[];\n };\n custom?: {\n families: string[];\n urls?: string[];\n };\n fontactive?: (familyName: string, fvd: string) => void;\n fontinactive?: (familyName: string, fvd: string) => void;\n active?: () => void;\n inactive?: () => void;\n}\n\n/**\n * Carga fuentes usando webfontloader de forma dinámica.\n * Esta función carga el módulo webfontloader solo cuando es necesario.\n * \n * @param fontConfig Configuración de fuentes para webfontloader\n * @returns Promise que se resuelve cuando las fuentes se cargan\n */\nexport async function loadFonts(fontConfig: FontConfig): Promise<void> {\n if (!fontConfig || (!fontConfig.google && !fontConfig.custom)) {\n return Promise.resolve();\n }\n\n try {\n // Importación dinámica de webfontloader\n // webfontloader puede exportar de diferentes formas según el entorno\n const webfontloaderModule = await import('webfontloader');\n const WebFont = webfontloaderModule.default || webfontloaderModule;\n \n if (!WebFont || typeof WebFont.load !== 'function') {\n console.warn('webfontloader no está disponible o no tiene el método load');\n return Promise.resolve();\n }\n \n return new Promise<void>((resolve) => {\n const config: any = {\n ...fontConfig,\n active: () => {\n if (fontConfig.active) {\n fontConfig.active();\n }\n resolve();\n },\n inactive: () => {\n if (fontConfig.inactive) {\n fontConfig.inactive();\n }\n // No rechazamos la promesa, solo resolvemos\n // para que el template pueda renderizarse con fuentes por defecto\n resolve();\n },\n };\n\n WebFont.load(config);\n });\n } catch (error) {\n console.error('Error loading webfontloader:', error);\n // Resolvemos en lugar de rechazar para que el template pueda renderizarse\n return Promise.resolve();\n }\n}\n\n/**\n * Aplica la familia de fuente al elemento raíz del componente.\n * \n * @param element Elemento HTML al que aplicar la fuente\n * @param fontFamily Familia de fuente CSS (ej: \"Roboto, sans-serif\")\n */\nexport function applyFontFamily(element: HTMLElement, fontFamily: string): void {\n if (fontFamily && element) {\n element.style.fontFamily = fontFamily;\n }\n}\n\n","/**\n * Formatea un precio como string con símbolo de euro.\n * Si es un número entero, no muestra decimales.\n */\nexport function formatPrice(price: number): string {\n return (price % 1 === 0 ? price.toString() : price.toFixed(2)) + '€';\n}\n\n\n\n",".menu-wrapper {\n min-height: 100vh;\n width: 100%;\n padding: 1.5rem 1rem;\n font-family: 'Merriweather', serif;\n /* Reset para aislar de estilos globales */\n box-sizing: border-box;\n margin: 0;\n display: block;\n}\n\n/* Asegurar que todos los elementos hijos usen border-box */\n.menu-wrapper *,\n.menu-wrapper *::before,\n.menu-wrapper *::after {\n box-sizing: border-box;\n}\n\n/* Reset completo de márgenes para todos los elementos HTML comunes */\n.menu-wrapper h1,\n.menu-wrapper h2,\n.menu-wrapper h3,\n.menu-wrapper h4,\n.menu-wrapper h5,\n.menu-wrapper h6,\n.menu-wrapper p,\n.menu-wrapper ul,\n.menu-wrapper ol,\n.menu-wrapper li,\n.menu-wrapper header,\n.menu-wrapper section,\n.menu-wrapper article,\n.menu-wrapper aside,\n.menu-wrapper nav,\n.menu-wrapper blockquote,\n.menu-wrapper figure,\n.menu-wrapper figcaption {\n margin: 0;\n margin-block-start: 0;\n margin-block-end: 0;\n margin-inline-start: 0;\n margin-inline-end: 0;\n}\n\n/* Reset adicional para padding en listas */\n.menu-wrapper ul,\n.menu-wrapper ol {\n padding: 0;\n}\n\n@media (min-width: 640px) {\n .menu-wrapper {\n padding: 2rem 1.5rem;\n }\n}\n\n@media (min-width: 768px) {\n .menu-wrapper {\n padding: 2rem 1rem;\n }\n}\n\n.menu-container {\n max-width: 1280px;\n margin: 0 auto;\n}\n\n.menu-header {\n text-align: center;\n}\n\n@media (min-width: 768px) {\n .menu-header {\n margin-bottom: 3rem;\n }\n}\n\n.restaurant-title {\n font-size: 2rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n line-height: 1.1;\n margin: 0 0 1.5rem 0!important;\n}\n\n@media (min-width: 640px) {\n .restaurant-title {\n font-size: 2.5rem;\n margin: 0 0 3rem 0!important;\n }\n}\n\n@media (min-width: 768px) {\n .restaurant-title {\n font-size: 3rem;\n }\n}\n\n@media (min-width: 1024px) {\n .restaurant-title {\n font-size: 3.5rem;\n }\n}\n\n.sections-container {\n display: grid;\n grid-template-columns: 1fr;\n gap: 3rem;\n}\n\n@media (min-width: 768px) {\n .sections-container {\n grid-template-columns: repeat(2, 1fr);\n gap: 4rem;\n }\n}\n\n.menu-section {\n display: flex;\n width: 100%;\n position: relative;\n}\n\n/* Título vertical izquierdo */\n.section-label-wrapper {\n position: relative;\n width: 3rem;\n flex-shrink: 0;\n margin-right: 1rem;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-end;\n}\n\n.section-label-line {\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n width: 1px;\n border-right: 1px solid;\n}\n\n.section-label {\n font-weight: 700;\n font-size: 1.125rem;\n text-transform: uppercase;\n letter-spacing: 0.15em;\n writing-mode: vertical-rl;\n transform: rotate(180deg);\n text-align: right;\n white-space: nowrap;\n margin: 0 0 0.5rem 0;\n margin-block-end: 0.5rem;\n position: absolute;\n top: 0;\n}\n\n@media (min-width: 640px) {\n .section-label {\n font-size: 1.2375rem;\n }\n}\n\n@media (min-width: 768px) {\n .section-label {\n font-size: 1.35rem;\n }\n}\n\n@media (min-width: 1024px) {\n .section-label {\n font-size: 1.51875rem;\n }\n}\n\n/* Contenido de la sección */\n.section-content {\n flex: 1;\n padding-top: 0.25rem;\n}\n\n.section-description {\n font-size: 0.875rem;\n font-style: italic;\n margin: 0 0 1rem 0!important;\n margin-block-end: 1rem;\n opacity: 0.75;\n color: inherit;\n}\n\n@media (min-width: 640px) {\n .section-description {\n font-size: 0.9625rem;\n }\n}\n\n@media (min-width: 768px) {\n .section-description {\n font-size: 1.05rem;\n }\n}\n\n@media (min-width: 1024px) {\n .section-description {\n font-size: 1.18125rem;\n }\n}\n\n.dishes-list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: flex;\n flex-direction: column;\n gap: 1rem;\n}\n\n.dish-item {\n position: relative;\n}\n\n.dish-header {\n display: flex;\n align-items: baseline;\n width: 100%;\n gap: 0.5rem;\n}\n\n.dish-name {\n font-size: 1rem;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n flex-shrink: 0;\n}\n\n@media (min-width: 640px) {\n .dish-name {\n font-size: 1.1rem;\n }\n}\n\n@media (min-width: 768px) {\n .dish-name {\n font-size: 1.2rem;\n }\n}\n\n@media (min-width: 1024px) {\n .dish-name {\n font-size: 1.35rem;\n }\n}\n\n.dish-dots {\n flex: 1;\n opacity: 0.25;\n border-bottom: 1px dotted;\n margin: 0 0.55rem;\n position: relative;\n top: -5px;\n border-color: currentColor;\n}\n\n.dish-price {\n font-size: 1rem;\n font-weight: 700;\n flex-shrink: 0;\n text-align: right;\n}\n\n@media (min-width: 640px) {\n .dish-price {\n font-size: 1.1rem;\n }\n}\n\n@media (min-width: 768px) {\n .dish-price {\n font-size: 1.2rem;\n }\n}\n\n@media (min-width: 1024px) {\n .dish-price {\n font-size: 1.35rem;\n }\n}\n\n.dish-description {\n font-size: 0.8125rem;\n margin-top: -0.9rem;\n line-height: 1.4;\n opacity: 0.7;\n color: inherit;\n}\n\n@media (min-width: 640px) {\n .dish-description {\n font-size: 0.9425rem;\n }\n}\n","import { Component, Prop, h, Element } from '@stencil/core';\nimport { Menu } from '../../types/interfaces';\nimport { loadFonts, applyFontFamily } from '../../utils/font-loader';\nimport { formatPrice } from '../../utils/data-helpers';\n\n@Component({\n tag: 'veleta-boston-template',\n styleUrl: 'boston-template.css',\n shadow: false,\n})\nexport class BostonTemplate {\n @Element() el: HTMLElement;\n\n @Prop() dataJson: string = '{}';\n\n private readonly fontConfig = {\n google: {\n families: ['Oswald:400,600,700', 'Merriweather:300,400,700'],\n },\n };\n\n async componentWillLoad() {\n await loadFonts(this.fontConfig);\n applyFontFamily(this.el, 'Merriweather, serif');\n }\n\n render() {\n let menuData: Menu | null = null;\n try {\n menuData = JSON.parse(this.dataJson);\n } catch (e) {\n console.warn('Invalid dataJson provided to veleta-boston-template');\n }\n\n const theme = menuData?.templateData?.theme;\n const primary = theme?.primaryColor || '#1a365d';\n const fontBody = 'Merriweather, serif';\n const fontTitle = 'Oswald, sans-serif';\n\n if (!menuData) {\n return <div class=\"menu-wrapper\" style={{ color: primary }}></div>;\n }\n\n const { sections, business } = menuData;\n // Ordenar secciones por 'order'\n const sortedSections = (sections || []).sort((a, b) => a.order - b.order);\n\n return (\n <div\n class=\"menu-wrapper\"\n style={{ color: primary }}\n >\n <div class=\"menu-container\">\n {business?.name && (\n <header class=\"menu-header\">\n <h1 class=\"restaurant-title\" style={{ fontFamily: fontTitle }}>\n {business.name}\n </h1>\n </header>\n )}\n\n {/* Layout: 1 columna mobile, 2 columnas tablet/desktop */}\n <div class=\"sections-container\">\n {sortedSections.map(section => {\n // Ordenar platos por 'order'\n const sectionDishes = (section.dishes || []).sort((a, b) => a.order - b.order);\n if (!sectionDishes.length) return null;\n\n return (\n <section key={section.id} class=\"menu-section\">\n {/* Título vertical izquierdo */}\n <div class=\"section-label-wrapper\">\n <div class=\"section-label-line\" style={{ borderColor: primary }}></div>\n <h2\n class=\"section-label\"\n style={{ fontFamily: fontTitle, color: primary }}\n >\n {section.title}\n </h2>\n </div>\n\n {/* Contenido de platos */}\n <div class=\"section-content\">\n {section.description && (\n <p class=\"section-description\" style={{ fontFamily: fontBody }}>\n {section.description}\n </p>\n )}\n\n <ul class=\"dishes-list\">\n {sectionDishes.map(dish => (\n <li key={dish.id} class=\"dish-item\">\n <div class=\"dish-header\">\n <h3\n class=\"dish-name\"\n style={{ fontFamily: fontTitle, color: primary }}\n >\n {dish.name}\n </h3>\n <div\n class=\"dish-dots\"\n ></div>\n <span\n class=\"dish-price\"\n style={{ fontFamily: fontTitle, color: primary }}\n >\n {formatPrice(dish.price)}\n </span>\n </div>\n {dish.description && (\n <p class=\"dish-description\" style={{ fontFamily: fontBody }}>\n {dish.description}\n </p>\n )}\n </li>\n ))}\n </ul>\n </div>\n </section>\n );\n })}\n </div>\n </div>\n </div>\n );\n }\n}"],"version":3}
@@ -99,14 +99,10 @@ var loadModule = (cmpMeta, hostRef, hmrVersionId) => {
99
99
  }
100
100
  switch(bundleId) {
101
101
 
102
- case 'veleta-demo-template':
102
+ case 'veleta-boston-template':
103
103
  return import(
104
104
  /* webpackMode: "lazy" */
105
- './veleta-demo-template.entry.js').then(processMod, consoleError);
106
- case 'veleta-menu-template-b':
107
- return import(
108
- /* webpackMode: "lazy" */
109
- './veleta-menu-template-b.entry.js').then(processMod, consoleError);
105
+ './veleta-boston-template.entry.js').then(processMod, consoleError);
110
106
  }
111
107
  }
112
108
  return import(
@@ -5,7 +5,7 @@ import { g as globalScripts } from './app-globals-DQuL1Twl.js';
5
5
  const defineCustomElements = async (win, options) => {
6
6
  if (typeof window === 'undefined') return undefined;
7
7
  await globalScripts();
8
- return bootstrapLazy([["veleta-demo-template",[[256,"veleta-demo-template",{"sectionsJson":[1,"sections-json"],"dishesJson":[1,"dishes-json"],"themeJson":[1,"theme-json"],"restaurantName":[1,"restaurant-name"]}]]],["veleta-menu-template-b",[[256,"veleta-menu-template-b",{"sectionsJson":[1,"sections-json"],"dishesJson":[1,"dishes-json"],"themeJson":[1,"theme-json"],"restaurantName":[1,"restaurant-name"]}]]]], options);
8
+ return bootstrapLazy([["veleta-boston-template",[[256,"veleta-boston-template",{"dataJson":[1,"data-json"]}]]]], options);
9
9
  };
10
10
 
11
11
  export { defineCustomElements };