@manidecp/nagp-stencil-ui-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/cjs/custom-modal.cjs.entry.js +35 -0
  2. package/dist/cjs/custom-modal.cjs.entry.js.map +1 -0
  3. package/dist/cjs/index-xXx7YX-n.js +1672 -0
  4. package/dist/cjs/index-xXx7YX-n.js.map +1 -0
  5. package/dist/cjs/index.cjs.js +5 -0
  6. package/dist/cjs/index.cjs.js.map +1 -0
  7. package/dist/cjs/loader.cjs.js +15 -0
  8. package/dist/cjs/loader.cjs.js.map +1 -0
  9. package/dist/cjs/meal-slot-card.cjs.entry.js +33 -0
  10. package/dist/cjs/meal-slot-card.cjs.entry.js.map +1 -0
  11. package/dist/cjs/nagp-recipe-ui-kit.cjs.js +27 -0
  12. package/dist/cjs/nagp-recipe-ui-kit.cjs.js.map +1 -0
  13. package/dist/cjs/recipe-badge.cjs.entry.js +25 -0
  14. package/dist/cjs/recipe-badge.cjs.entry.js.map +1 -0
  15. package/dist/cjs/recipe-card.cjs.entry.js +59 -0
  16. package/dist/cjs/recipe-card.cjs.entry.js.map +1 -0
  17. package/dist/cjs/recipe-rating.cjs.entry.js +62 -0
  18. package/dist/cjs/recipe-rating.cjs.entry.js.map +1 -0
  19. package/dist/collection/collection-manifest.json +17 -0
  20. package/dist/collection/components/custom-modal/custom-modal.css +63 -0
  21. package/dist/collection/components/custom-modal/custom-modal.js +95 -0
  22. package/dist/collection/components/custom-modal/custom-modal.js.map +1 -0
  23. package/dist/collection/components/meal-slot-card/meal-slot-card.css +72 -0
  24. package/dist/collection/components/meal-slot-card/meal-slot-card.js +127 -0
  25. package/dist/collection/components/meal-slot-card/meal-slot-card.js.map +1 -0
  26. package/dist/collection/components/recipe-badge/recipe-badge.css +33 -0
  27. package/dist/collection/components/recipe-badge/recipe-badge.js +87 -0
  28. package/dist/collection/components/recipe-badge/recipe-badge.js.map +1 -0
  29. package/dist/collection/components/recipe-card/recipe-card.css +96 -0
  30. package/dist/collection/components/recipe-card/recipe-card.js +220 -0
  31. package/dist/collection/components/recipe-card/recipe-card.js.map +1 -0
  32. package/dist/collection/components/recipe-rating/recipe-rating.css +36 -0
  33. package/dist/collection/components/recipe-rating/recipe-rating.js +186 -0
  34. package/dist/collection/components/recipe-rating/recipe-rating.js.map +1 -0
  35. package/dist/collection/index.js +2 -0
  36. package/dist/collection/index.js.map +1 -0
  37. package/dist/components/custom-modal.d.ts +11 -0
  38. package/dist/components/custom-modal.js +2 -0
  39. package/dist/components/custom-modal.js.map +1 -0
  40. package/dist/components/index.d.ts +35 -0
  41. package/dist/components/index.js +2 -0
  42. package/dist/components/index.js.map +1 -0
  43. package/dist/components/meal-slot-card.d.ts +11 -0
  44. package/dist/components/meal-slot-card.js +2 -0
  45. package/dist/components/meal-slot-card.js.map +1 -0
  46. package/dist/components/recipe-badge.d.ts +11 -0
  47. package/dist/components/recipe-badge.js +2 -0
  48. package/dist/components/recipe-badge.js.map +1 -0
  49. package/dist/components/recipe-card.d.ts +11 -0
  50. package/dist/components/recipe-card.js +2 -0
  51. package/dist/components/recipe-card.js.map +1 -0
  52. package/dist/components/recipe-rating.d.ts +11 -0
  53. package/dist/components/recipe-rating.js +2 -0
  54. package/dist/components/recipe-rating.js.map +1 -0
  55. package/dist/esm/custom-modal.entry.js +33 -0
  56. package/dist/esm/custom-modal.entry.js.map +1 -0
  57. package/dist/esm/index-DrjLtd7S.js +1646 -0
  58. package/dist/esm/index-DrjLtd7S.js.map +1 -0
  59. package/dist/esm/index.js +4 -0
  60. package/dist/esm/index.js.map +1 -0
  61. package/dist/esm/loader.js +13 -0
  62. package/dist/esm/loader.js.map +1 -0
  63. package/dist/esm/meal-slot-card.entry.js +31 -0
  64. package/dist/esm/meal-slot-card.entry.js.map +1 -0
  65. package/dist/esm/nagp-recipe-ui-kit.js +23 -0
  66. package/dist/esm/nagp-recipe-ui-kit.js.map +1 -0
  67. package/dist/esm/recipe-badge.entry.js +23 -0
  68. package/dist/esm/recipe-badge.entry.js.map +1 -0
  69. package/dist/esm/recipe-card.entry.js +57 -0
  70. package/dist/esm/recipe-card.entry.js.map +1 -0
  71. package/dist/esm/recipe-rating.entry.js +60 -0
  72. package/dist/esm/recipe-rating.entry.js.map +1 -0
  73. package/dist/index.cjs.js +1 -0
  74. package/dist/index.js +1 -0
  75. package/dist/nagp-recipe-ui-kit/index.esm.js +2 -0
  76. package/dist/nagp-recipe-ui-kit/index.esm.js.map +1 -0
  77. package/dist/nagp-recipe-ui-kit/nagp-recipe-ui-kit.css +1 -0
  78. package/dist/nagp-recipe-ui-kit/nagp-recipe-ui-kit.esm.js +2 -0
  79. package/dist/nagp-recipe-ui-kit/nagp-recipe-ui-kit.esm.js.map +1 -0
  80. package/dist/nagp-recipe-ui-kit/p-21d809b9.entry.js +2 -0
  81. package/dist/nagp-recipe-ui-kit/p-21d809b9.entry.js.map +1 -0
  82. package/dist/nagp-recipe-ui-kit/p-524e6762.entry.js +2 -0
  83. package/dist/nagp-recipe-ui-kit/p-524e6762.entry.js.map +1 -0
  84. package/dist/nagp-recipe-ui-kit/p-DrjLtd7S.js +3 -0
  85. package/dist/nagp-recipe-ui-kit/p-DrjLtd7S.js.map +1 -0
  86. package/dist/nagp-recipe-ui-kit/p-cfec107f.entry.js +2 -0
  87. package/dist/nagp-recipe-ui-kit/p-cfec107f.entry.js.map +1 -0
  88. package/dist/nagp-recipe-ui-kit/p-de6ef31c.entry.js +2 -0
  89. package/dist/nagp-recipe-ui-kit/p-de6ef31c.entry.js.map +1 -0
  90. package/dist/nagp-recipe-ui-kit/p-e8a2f5f9.entry.js +2 -0
  91. package/dist/nagp-recipe-ui-kit/p-e8a2f5f9.entry.js.map +1 -0
  92. package/dist/types/components/custom-modal/custom-modal.d.ts +9 -0
  93. package/dist/types/components/meal-slot-card/meal-slot-card.d.ts +17 -0
  94. package/dist/types/components/recipe-badge/recipe-badge.d.ts +6 -0
  95. package/dist/types/components/recipe-card/recipe-card.d.ts +24 -0
  96. package/dist/types/components/recipe-rating/recipe-rating.d.ts +16 -0
  97. package/dist/types/components.d.ts +314 -0
  98. package/dist/types/index.d.ts +1 -0
  99. package/dist/types/stencil-public-runtime.d.ts +1873 -0
  100. package/package.json +32 -0
@@ -0,0 +1,127 @@
1
+ import { h } from "@stencil/core";
2
+ export class MealSlotCard {
3
+ day = 'Monday';
4
+ mealType = 'Dinner';
5
+ recipeName = 'No meal selected';
6
+ removeMeal;
7
+ addMeal;
8
+ handleAddMeal = () => {
9
+ this.addMeal.emit({ day: this.day, mealType: this.mealType });
10
+ };
11
+ handleRemoveMeal = () => {
12
+ this.removeMeal.emit({ day: this.day, mealType: this.mealType });
13
+ };
14
+ render() {
15
+ return (h("article", { key: 'fa9eb478dc830300b8cb795e315e630222c99ae9', class: "meal-slot-card" }, h("header", { key: 'da28c71efc7e22dea6b3c0e31a0a002cd49407e1', class: "card-header" }, h("span", { key: '690e9ae3282df47b991fcf9903b0fc549b76a455', class: "day-label" }, this.day), h("span", { key: '50bc7ed1f5aae519fa9233cdccc02fae13c4fabb', class: "meal-pill" }, this.mealType)), h("div", { key: '157360002668cea4b02436cf7afedb6232007f77', class: "content" }, h("h3", { key: '5c9121084ad9f1b152b51e2db034576cf38f5b03' }, this.recipeName), h("slot", { key: 'b60f501af76e15758c53f29bd66dbab7f196c859' })), h("div", { key: '2572b419e6e0d2f74027e0bf6ef2b1a83245b9ae', class: "actions" }, h("button", { key: '610ea49c7bc1f9b43ef2cff9855a237168c95408', type: "button", class: "primary", onClick: this.handleAddMeal }, "Add meal"), h("button", { key: '0511efe9d57aee3243e06ad43294cd1c4cc2b31b', type: "button", class: "secondary", onClick: this.handleRemoveMeal }, "Remove"))));
16
+ }
17
+ static get is() { return "meal-slot-card"; }
18
+ static get encapsulation() { return "shadow"; }
19
+ static get originalStyleUrls() {
20
+ return {
21
+ "$": ["meal-slot-card.css"]
22
+ };
23
+ }
24
+ static get styleUrls() {
25
+ return {
26
+ "$": ["meal-slot-card.css"]
27
+ };
28
+ }
29
+ static get properties() {
30
+ return {
31
+ "day": {
32
+ "type": "string",
33
+ "mutable": false,
34
+ "complexType": {
35
+ "original": "string",
36
+ "resolved": "string",
37
+ "references": {}
38
+ },
39
+ "required": false,
40
+ "optional": false,
41
+ "docs": {
42
+ "tags": [],
43
+ "text": ""
44
+ },
45
+ "getter": false,
46
+ "setter": false,
47
+ "reflect": false,
48
+ "attribute": "day",
49
+ "defaultValue": "'Monday'"
50
+ },
51
+ "mealType": {
52
+ "type": "string",
53
+ "mutable": false,
54
+ "complexType": {
55
+ "original": "'Breakfast' | 'Lunch' | 'Dinner'",
56
+ "resolved": "\"Breakfast\" | \"Dinner\" | \"Lunch\"",
57
+ "references": {}
58
+ },
59
+ "required": false,
60
+ "optional": false,
61
+ "docs": {
62
+ "tags": [],
63
+ "text": ""
64
+ },
65
+ "getter": false,
66
+ "setter": false,
67
+ "reflect": false,
68
+ "attribute": "meal-type",
69
+ "defaultValue": "'Dinner'"
70
+ },
71
+ "recipeName": {
72
+ "type": "string",
73
+ "mutable": false,
74
+ "complexType": {
75
+ "original": "string",
76
+ "resolved": "string",
77
+ "references": {}
78
+ },
79
+ "required": false,
80
+ "optional": false,
81
+ "docs": {
82
+ "tags": [],
83
+ "text": ""
84
+ },
85
+ "getter": false,
86
+ "setter": false,
87
+ "reflect": false,
88
+ "attribute": "recipe-name",
89
+ "defaultValue": "'No meal selected'"
90
+ }
91
+ };
92
+ }
93
+ static get events() {
94
+ return [{
95
+ "method": "removeMeal",
96
+ "name": "removeMeal",
97
+ "bubbles": true,
98
+ "cancelable": true,
99
+ "composed": true,
100
+ "docs": {
101
+ "tags": [],
102
+ "text": ""
103
+ },
104
+ "complexType": {
105
+ "original": "{ day: string; mealType: 'Breakfast' | 'Lunch' | 'Dinner' }",
106
+ "resolved": "{ day: string; mealType: \"Breakfast\" | \"Lunch\" | \"Dinner\"; }",
107
+ "references": {}
108
+ }
109
+ }, {
110
+ "method": "addMeal",
111
+ "name": "addMeal",
112
+ "bubbles": true,
113
+ "cancelable": true,
114
+ "composed": true,
115
+ "docs": {
116
+ "tags": [],
117
+ "text": ""
118
+ },
119
+ "complexType": {
120
+ "original": "{ day: string; mealType: 'Breakfast' | 'Lunch' | 'Dinner' }",
121
+ "resolved": "{ day: string; mealType: \"Breakfast\" | \"Lunch\" | \"Dinner\"; }",
122
+ "references": {}
123
+ }
124
+ }];
125
+ }
126
+ }
127
+ //# sourceMappingURL=meal-slot-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meal-slot-card.js","sourceRoot":"","sources":["../../../src/components/meal-slot-card/meal-slot-card.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AAOxE,MAAM,OAAO,YAAY;IACf,GAAG,GAAW,QAAQ,CAAC;IACvB,QAAQ,GAAqC,QAAQ,CAAC;IACtD,UAAU,GAAW,kBAAkB,CAAC;IAEvC,UAAU,CAA4E;IACtF,OAAO,CAA4E;IAEpF,aAAa,GAAG,GAAG,EAAE;QAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC;IAEM,gBAAgB,GAAG,GAAG,EAAE;QAC9B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC;IAEF,MAAM;QACJ,OAAO,CACL,gEAAS,KAAK,EAAC,gBAAgB;YAC7B,+DAAQ,KAAK,EAAC,aAAa;gBACzB,6DAAM,KAAK,EAAC,WAAW,IAAE,IAAI,CAAC,GAAG,CAAQ;gBACzC,6DAAM,KAAK,EAAC,WAAW,IAAE,IAAI,CAAC,QAAQ,CAAQ,CACvC;YAET,4DAAK,KAAK,EAAC,SAAS;gBAClB,6DAAK,IAAI,CAAC,UAAU,CAAM;gBAC1B,8DAAQ,CACJ;YAEN,4DAAK,KAAK,EAAC,SAAS;gBAClB,+DAAQ,IAAI,EAAC,QAAQ,EAAC,KAAK,EAAC,SAAS,EAAC,OAAO,EAAE,IAAI,CAAC,aAAa,eAExD;gBACT,+DAAQ,IAAI,EAAC,QAAQ,EAAC,KAAK,EAAC,WAAW,EAAC,OAAO,EAAE,IAAI,CAAC,gBAAgB,aAE7D,CACL,CACE,CACX,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, h, Prop, Event, EventEmitter } from '@stencil/core';\r\n\r\n@Component({\r\n tag: 'meal-slot-card',\r\n styleUrl: 'meal-slot-card.css',\r\n shadow: true,\r\n})\r\nexport class MealSlotCard {\r\n @Prop() day: string = 'Monday';\r\n @Prop() mealType: 'Breakfast' | 'Lunch' | 'Dinner' = 'Dinner';\r\n @Prop() recipeName: string = 'No meal selected';\r\n\r\n @Event() removeMeal: EventEmitter<{ day: string; mealType: 'Breakfast' | 'Lunch' | 'Dinner' }>;\r\n @Event() addMeal: EventEmitter<{ day: string; mealType: 'Breakfast' | 'Lunch' | 'Dinner' }>;\r\n\r\n private handleAddMeal = () => {\r\n this.addMeal.emit({ day: this.day, mealType: this.mealType });\r\n };\r\n\r\n private handleRemoveMeal = () => {\r\n this.removeMeal.emit({ day: this.day, mealType: this.mealType });\r\n };\r\n\r\n render() {\r\n return (\r\n <article class=\"meal-slot-card\">\r\n <header class=\"card-header\">\r\n <span class=\"day-label\">{this.day}</span>\r\n <span class=\"meal-pill\">{this.mealType}</span>\r\n </header>\r\n\r\n <div class=\"content\">\r\n <h3>{this.recipeName}</h3>\r\n <slot />\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button type=\"button\" class=\"primary\" onClick={this.handleAddMeal}>\r\n Add meal\r\n </button>\r\n <button type=\"button\" class=\"secondary\" onClick={this.handleRemoveMeal}>\r\n Remove\r\n </button>\r\n </div>\r\n </article>\r\n );\r\n }\r\n}\r\n"]}
@@ -0,0 +1,33 @@
1
+ :host {
2
+ --badge-primary-bg: #f97316;
3
+ --badge-secondary-bg: #e5e7eb;
4
+ --badge-accent-bg: #7c3aed;
5
+ --badge-text: #ffffff;
6
+ display: inline-block;
7
+ }
8
+
9
+ .badge {
10
+ display: inline-flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ border-radius: 999px;
14
+ padding: 0.45rem 0.8rem;
15
+ font-size: 0.7rem;
16
+ font-weight: 800;
17
+ letter-spacing: 0.06em;
18
+ text-transform: uppercase;
19
+ color: var(--badge-text);
20
+ }
21
+
22
+ .variant-primary {
23
+ background: var(--badge-primary-bg);
24
+ }
25
+
26
+ .variant-secondary {
27
+ background: var(--badge-secondary-bg);
28
+ color: #111827;
29
+ }
30
+
31
+ .variant-accent {
32
+ background: var(--badge-accent-bg);
33
+ }
@@ -0,0 +1,87 @@
1
+ import { h } from "@stencil/core";
2
+ export class RecipeBadge {
3
+ label = 'Featured';
4
+ variant = 'primary';
5
+ // Backward-compatible alias for the original scaffolded API.
6
+ color;
7
+ render() {
8
+ const style = this.color ? { background: this.color } : {};
9
+ return (h("span", { key: '35180a6a6346c97293dc0ddadb0819b7aa1ff9e5', class: { badge: true, [`variant-${this.variant}`]: true }, style: style }, this.label));
10
+ }
11
+ static get is() { return "recipe-badge"; }
12
+ static get encapsulation() { return "shadow"; }
13
+ static get originalStyleUrls() {
14
+ return {
15
+ "$": ["recipe-badge.css"]
16
+ };
17
+ }
18
+ static get styleUrls() {
19
+ return {
20
+ "$": ["recipe-badge.css"]
21
+ };
22
+ }
23
+ static get properties() {
24
+ return {
25
+ "label": {
26
+ "type": "string",
27
+ "mutable": false,
28
+ "complexType": {
29
+ "original": "string",
30
+ "resolved": "string",
31
+ "references": {}
32
+ },
33
+ "required": false,
34
+ "optional": false,
35
+ "docs": {
36
+ "tags": [],
37
+ "text": ""
38
+ },
39
+ "getter": false,
40
+ "setter": false,
41
+ "reflect": false,
42
+ "attribute": "label",
43
+ "defaultValue": "'Featured'"
44
+ },
45
+ "variant": {
46
+ "type": "string",
47
+ "mutable": false,
48
+ "complexType": {
49
+ "original": "'primary' | 'secondary' | 'accent'",
50
+ "resolved": "\"accent\" | \"primary\" | \"secondary\"",
51
+ "references": {}
52
+ },
53
+ "required": false,
54
+ "optional": false,
55
+ "docs": {
56
+ "tags": [],
57
+ "text": ""
58
+ },
59
+ "getter": false,
60
+ "setter": false,
61
+ "reflect": false,
62
+ "attribute": "variant",
63
+ "defaultValue": "'primary'"
64
+ },
65
+ "color": {
66
+ "type": "string",
67
+ "mutable": false,
68
+ "complexType": {
69
+ "original": "string",
70
+ "resolved": "string",
71
+ "references": {}
72
+ },
73
+ "required": false,
74
+ "optional": false,
75
+ "docs": {
76
+ "tags": [],
77
+ "text": ""
78
+ },
79
+ "getter": false,
80
+ "setter": false,
81
+ "reflect": false,
82
+ "attribute": "color"
83
+ }
84
+ };
85
+ }
86
+ }
87
+ //# sourceMappingURL=recipe-badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe-badge.js","sourceRoot":"","sources":["../../../src/components/recipe-badge/recipe-badge.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAOnD,MAAM,OAAO,WAAW;IACd,KAAK,GAAW,UAAU,CAAC;IAC3B,OAAO,GAAuC,SAAS,CAAC;IAEhE,6DAA6D;IACrD,KAAK,CAAS;IAEtB,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,CACL,6DAAM,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,IAC1E,IAAI,CAAC,KAAK,CACN,CACR,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, h, Prop } from '@stencil/core';\r\n\r\n@Component({\r\n tag: 'recipe-badge',\r\n styleUrl: 'recipe-badge.css',\r\n shadow: true,\r\n})\r\nexport class RecipeBadge {\r\n @Prop() label: string = 'Featured';\r\n @Prop() variant: 'primary' | 'secondary' | 'accent' = 'primary';\r\n\r\n // Backward-compatible alias for the original scaffolded API.\r\n @Prop() color: string;\r\n\r\n render() {\r\n const style = this.color ? { background: this.color } : {};\r\n return (\r\n <span class={{ badge: true, [`variant-${this.variant}`]: true }} style={style}>\r\n {this.label}\r\n </span>\r\n );\r\n }\r\n}\r\n"]}
@@ -0,0 +1,96 @@
1
+ :host {
2
+ --recipe-card-bg: #ffffff;
3
+ --recipe-card-text: #111827;
4
+ --recipe-card-muted: #6b7280;
5
+ --recipe-card-accent: #f97316;
6
+ --recipe-card-border: #e5e7eb;
7
+ display: block;
8
+ }
9
+
10
+ .recipe-card {
11
+ background: var(--recipe-card-bg);
12
+ border: 1px solid var(--recipe-card-border);
13
+ border-radius: 18px;
14
+ overflow: hidden;
15
+ box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
16
+ cursor: pointer;
17
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
18
+ }
19
+
20
+ .recipe-card:hover {
21
+ transform: translateY(-2px);
22
+ box-shadow: 0 18px 32px rgba(15, 23, 42, 0.12);
23
+ }
24
+
25
+ .image-wrap {
26
+ position: relative;
27
+ height: 180px;
28
+ background: linear-gradient(135deg, #fff7ed, #ffedd5);
29
+ }
30
+
31
+ .image-wrap img,
32
+ .image-placeholder {
33
+ width: 100%;
34
+ height: 100%;
35
+ display: block;
36
+ object-fit: cover;
37
+ }
38
+
39
+ .image-placeholder {
40
+ display: grid;
41
+ place-items: center;
42
+ font-weight: 700;
43
+ letter-spacing: 0.08em;
44
+ text-transform: uppercase;
45
+ color: var(--recipe-card-accent);
46
+ }
47
+
48
+ .favorite {
49
+ position: absolute;
50
+ top: 12px;
51
+ right: 12px;
52
+ width: 2.5rem;
53
+ height: 2.5rem;
54
+ border: none;
55
+ border-radius: 50%;
56
+ background: rgba(255, 255, 255, 0.9);
57
+ color: #9ca3af;
58
+ font-size: 1.2rem;
59
+ cursor: pointer;
60
+ }
61
+
62
+ .favorite.active {
63
+ background: rgba(249, 115, 22, 0.12);
64
+ color: var(--recipe-card-accent);
65
+ }
66
+
67
+ .card-content {
68
+ padding: 1rem;
69
+ }
70
+
71
+ .meta-row {
72
+ display: flex;
73
+ justify-content: flex-end;
74
+ margin-bottom: 0.5rem;
75
+ }
76
+
77
+ .prep-time {
78
+ font-size: 0.75rem;
79
+ font-weight: 700;
80
+ letter-spacing: 0.04em;
81
+ text-transform: uppercase;
82
+ color: var(--recipe-card-accent);
83
+ }
84
+
85
+ h2 {
86
+ margin: 0 0 0.75rem;
87
+ font-size: 1.25rem;
88
+ color: var(--recipe-card-text);
89
+ }
90
+
91
+ .actions-row {
92
+ display: flex;
93
+ justify-content: flex-end;
94
+ align-items: center;
95
+ gap: 0.5rem;
96
+ }
@@ -0,0 +1,220 @@
1
+ import { h } from "@stencil/core";
2
+ export class RecipeCard {
3
+ recipeId = 'recipe-1';
4
+ recipeTitle = 'Spicy Pasta';
5
+ imageUrl = '';
6
+ prepTime = 30;
7
+ isFavorite = false;
8
+ favoriteState = false;
9
+ cardClick;
10
+ favoriteToggle;
11
+ componentWillLoad() {
12
+ this.favoriteState = this.isFavorite;
13
+ }
14
+ handleFavoritePropChange(newValue) {
15
+ this.favoriteState = newValue;
16
+ }
17
+ async toggleFavorite() {
18
+ this.favoriteState = !this.favoriteState;
19
+ this.favoriteToggle.emit({
20
+ recipeId: this.recipeId,
21
+ recipeTitle: this.recipeTitle,
22
+ isFavorite: this.favoriteState,
23
+ });
24
+ }
25
+ handleCardClick = () => {
26
+ this.cardClick.emit({
27
+ recipeId: this.recipeId,
28
+ recipeTitle: this.recipeTitle,
29
+ });
30
+ };
31
+ handleFavoriteClick = (event) => {
32
+ event.stopPropagation();
33
+ this.toggleFavorite();
34
+ };
35
+ render() {
36
+ return (h("article", { key: 'ea8d57192146e0c875ba9c357ea5e65ddf4e2c5e', class: "recipe-card", onClick: this.handleCardClick }, h("div", { key: 'f6dfc3b4481988fd07d23cd0548f1cb1984942f5', class: "image-wrap" }, this.imageUrl ? (h("img", { src: this.imageUrl, alt: this.recipeTitle })) : (h("div", { class: "image-placeholder" }, "Recipe")), h("button", { key: 'f024d1784c817c7bb2ad937444365be8d192d4f8', type: "button", class: { favorite: true, active: this.favoriteState }, "aria-label": this.favoriteState ? 'Remove favorite' : 'Add favorite', onClick: this.handleFavoriteClick }, this.favoriteState ? '♥' : '♡')), h("div", { key: 'e44fb2e9d90c8ef20d05a1f1baabc7d1e1b7a070', class: "card-content" }, h("div", { key: 'e34a861b6f82d9368d400d0115a329bf3a9b91f4', class: "meta-row" }, h("span", { key: '925e5a0682f4923d51c28b07348b403ddac19065', class: "prep-time" }, this.prepTime, " min")), h("h2", { key: '7a576e9ed4af7fa83a5e34400ad2a0cfb32f7a1c' }, this.recipeTitle), h("div", { key: 'd4f3a287d889da78d1a785183aa43c53f9546c36', class: "actions-row" }, h("slot", { key: 'aeb6163d6243fbc55cf98f5fd7c3fbbf59a1a6e9', name: "actions" })))));
37
+ }
38
+ static get is() { return "recipe-card"; }
39
+ static get encapsulation() { return "shadow"; }
40
+ static get originalStyleUrls() {
41
+ return {
42
+ "$": ["recipe-card.css"]
43
+ };
44
+ }
45
+ static get styleUrls() {
46
+ return {
47
+ "$": ["recipe-card.css"]
48
+ };
49
+ }
50
+ static get properties() {
51
+ return {
52
+ "recipeId": {
53
+ "type": "string",
54
+ "mutable": false,
55
+ "complexType": {
56
+ "original": "string",
57
+ "resolved": "string",
58
+ "references": {}
59
+ },
60
+ "required": false,
61
+ "optional": false,
62
+ "docs": {
63
+ "tags": [],
64
+ "text": ""
65
+ },
66
+ "getter": false,
67
+ "setter": false,
68
+ "reflect": false,
69
+ "attribute": "recipe-id",
70
+ "defaultValue": "'recipe-1'"
71
+ },
72
+ "recipeTitle": {
73
+ "type": "string",
74
+ "mutable": false,
75
+ "complexType": {
76
+ "original": "string",
77
+ "resolved": "string",
78
+ "references": {}
79
+ },
80
+ "required": false,
81
+ "optional": false,
82
+ "docs": {
83
+ "tags": [],
84
+ "text": ""
85
+ },
86
+ "getter": false,
87
+ "setter": false,
88
+ "reflect": false,
89
+ "attribute": "recipe-title",
90
+ "defaultValue": "'Spicy Pasta'"
91
+ },
92
+ "imageUrl": {
93
+ "type": "string",
94
+ "mutable": false,
95
+ "complexType": {
96
+ "original": "string",
97
+ "resolved": "string",
98
+ "references": {}
99
+ },
100
+ "required": false,
101
+ "optional": false,
102
+ "docs": {
103
+ "tags": [],
104
+ "text": ""
105
+ },
106
+ "getter": false,
107
+ "setter": false,
108
+ "reflect": false,
109
+ "attribute": "image-url",
110
+ "defaultValue": "''"
111
+ },
112
+ "prepTime": {
113
+ "type": "number",
114
+ "mutable": false,
115
+ "complexType": {
116
+ "original": "number",
117
+ "resolved": "number",
118
+ "references": {}
119
+ },
120
+ "required": false,
121
+ "optional": false,
122
+ "docs": {
123
+ "tags": [],
124
+ "text": ""
125
+ },
126
+ "getter": false,
127
+ "setter": false,
128
+ "reflect": false,
129
+ "attribute": "prep-time",
130
+ "defaultValue": "30"
131
+ },
132
+ "isFavorite": {
133
+ "type": "boolean",
134
+ "mutable": false,
135
+ "complexType": {
136
+ "original": "boolean",
137
+ "resolved": "boolean",
138
+ "references": {}
139
+ },
140
+ "required": false,
141
+ "optional": false,
142
+ "docs": {
143
+ "tags": [],
144
+ "text": ""
145
+ },
146
+ "getter": false,
147
+ "setter": false,
148
+ "reflect": false,
149
+ "attribute": "is-favorite",
150
+ "defaultValue": "false"
151
+ }
152
+ };
153
+ }
154
+ static get states() {
155
+ return {
156
+ "favoriteState": {}
157
+ };
158
+ }
159
+ static get events() {
160
+ return [{
161
+ "method": "cardClick",
162
+ "name": "cardClick",
163
+ "bubbles": true,
164
+ "cancelable": true,
165
+ "composed": true,
166
+ "docs": {
167
+ "tags": [],
168
+ "text": ""
169
+ },
170
+ "complexType": {
171
+ "original": "{ recipeId: string; recipeTitle: string }",
172
+ "resolved": "{ recipeId: string; recipeTitle: string; }",
173
+ "references": {}
174
+ }
175
+ }, {
176
+ "method": "favoriteToggle",
177
+ "name": "favoriteToggle",
178
+ "bubbles": true,
179
+ "cancelable": true,
180
+ "composed": true,
181
+ "docs": {
182
+ "tags": [],
183
+ "text": ""
184
+ },
185
+ "complexType": {
186
+ "original": "{ recipeId: string; recipeTitle: string; isFavorite: boolean }",
187
+ "resolved": "{ recipeId: string; recipeTitle: string; isFavorite: boolean; }",
188
+ "references": {}
189
+ }
190
+ }];
191
+ }
192
+ static get methods() {
193
+ return {
194
+ "toggleFavorite": {
195
+ "complexType": {
196
+ "signature": "() => Promise<void>",
197
+ "parameters": [],
198
+ "references": {
199
+ "Promise": {
200
+ "location": "global",
201
+ "id": "global::Promise"
202
+ }
203
+ },
204
+ "return": "Promise<void>"
205
+ },
206
+ "docs": {
207
+ "text": "",
208
+ "tags": []
209
+ }
210
+ }
211
+ };
212
+ }
213
+ static get watchers() {
214
+ return [{
215
+ "propName": "isFavorite",
216
+ "methodName": "handleFavoritePropChange"
217
+ }];
218
+ }
219
+ }
220
+ //# sourceMappingURL=recipe-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe-card.js","sourceRoot":"","sources":["../../../src/components/recipe-card/recipe-card.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAgB,MAAM,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAO9F,MAAM,OAAO,UAAU;IACb,QAAQ,GAAW,UAAU,CAAC;IAC9B,WAAW,GAAW,aAAa,CAAC;IACpC,QAAQ,GAAW,EAAE,CAAC;IACtB,QAAQ,GAAW,EAAE,CAAC;IACtB,UAAU,GAAY,KAAK,CAAC;IAE3B,aAAa,GAAY,KAAK,CAAC;IAE/B,SAAS,CAA0D;IACnE,cAAc,CAA+E;IAEtG,iBAAiB;QACf,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC;IACvC,CAAC;IAGD,wBAAwB,CAAC,QAAiB;QACxC,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;IAChC,CAAC;IAGD,KAAK,CAAC,cAAc;QAClB,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC;QACzC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,aAAa;SAC/B,CAAC,CAAC;IACL,CAAC;IAEO,eAAe,GAAG,GAAG,EAAE;QAC7B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAClB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC;IAEM,mBAAmB,GAAG,CAAC,KAAY,EAAE,EAAE;QAC7C,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC,CAAC;IAEF,MAAM;QACJ,OAAO,CACL,gEAAS,KAAK,EAAC,aAAa,EAAC,OAAO,EAAE,IAAI,CAAC,eAAe;YACxD,4DAAK,KAAK,EAAC,YAAY;gBACpB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CACf,WAAK,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,WAAW,GAAI,CACnD,CAAC,CAAC,CAAC,CACF,WAAK,KAAK,EAAC,mBAAmB,aAAa,CAC5C;gBACD,+DACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,gBACzC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,cAAc,EACnE,OAAO,EAAE,IAAI,CAAC,mBAAmB,IAEhC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CACxB,CACL;YAEN,4DAAK,KAAK,EAAC,cAAc;gBACvB,4DAAK,KAAK,EAAC,UAAU;oBACnB,6DAAM,KAAK,EAAC,WAAW;wBAAE,IAAI,CAAC,QAAQ;+BAAY,CAC9C;gBACN,6DAAK,IAAI,CAAC,WAAW,CAAM;gBAC3B,4DAAK,KAAK,EAAC,aAAa;oBACtB,6DAAM,IAAI,EAAC,SAAS,GAAG,CACnB,CACF,CACE,CACX,CAAC;IACJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACF","sourcesContent":["import { Component, h, Prop, State, Event, EventEmitter, Method, Watch } from '@stencil/core';\r\n\r\n@Component({\r\n tag: 'recipe-card',\r\n styleUrl: 'recipe-card.css',\r\n shadow: true,\r\n})\r\nexport class RecipeCard {\r\n @Prop() recipeId: string = 'recipe-1';\r\n @Prop() recipeTitle: string = 'Spicy Pasta';\r\n @Prop() imageUrl: string = '';\r\n @Prop() prepTime: number = 30;\r\n @Prop() isFavorite: boolean = false;\r\n\r\n @State() favoriteState: boolean = false;\r\n\r\n @Event() cardClick: EventEmitter<{ recipeId: string; recipeTitle: string }>;\r\n @Event() favoriteToggle: EventEmitter<{ recipeId: string; recipeTitle: string; isFavorite: boolean }>;\r\n\r\n componentWillLoad() {\r\n this.favoriteState = this.isFavorite;\r\n }\r\n\r\n @Watch('isFavorite')\r\n handleFavoritePropChange(newValue: boolean) {\r\n this.favoriteState = newValue;\r\n }\r\n\r\n @Method()\r\n async toggleFavorite() {\r\n this.favoriteState = !this.favoriteState;\r\n this.favoriteToggle.emit({\r\n recipeId: this.recipeId,\r\n recipeTitle: this.recipeTitle,\r\n isFavorite: this.favoriteState,\r\n });\r\n }\r\n\r\n private handleCardClick = () => {\r\n this.cardClick.emit({\r\n recipeId: this.recipeId,\r\n recipeTitle: this.recipeTitle,\r\n });\r\n };\r\n\r\n private handleFavoriteClick = (event: Event) => {\r\n event.stopPropagation();\r\n this.toggleFavorite();\r\n };\r\n\r\n render() {\r\n return (\r\n <article class=\"recipe-card\" onClick={this.handleCardClick}>\r\n <div class=\"image-wrap\">\r\n {this.imageUrl ? (\r\n <img src={this.imageUrl} alt={this.recipeTitle} />\r\n ) : (\r\n <div class=\"image-placeholder\">Recipe</div>\r\n )}\r\n <button\r\n type=\"button\"\r\n class={{ favorite: true, active: this.favoriteState }}\r\n aria-label={this.favoriteState ? 'Remove favorite' : 'Add favorite'}\r\n onClick={this.handleFavoriteClick}\r\n >\r\n {this.favoriteState ? '♥' : '♡'}\r\n </button>\r\n </div>\r\n\r\n <div class=\"card-content\">\r\n <div class=\"meta-row\">\r\n <span class=\"prep-time\">{this.prepTime} min</span>\r\n </div>\r\n <h2>{this.recipeTitle}</h2>\r\n <div class=\"actions-row\">\r\n <slot name=\"actions\" />\r\n </div>\r\n </div>\r\n </article>\r\n );\r\n }\r\n}\r\n"]}
@@ -0,0 +1,36 @@
1
+ :host {
2
+ --rating-filled: #fbbf24;
3
+ --rating-empty: #d1d5db;
4
+ display: inline-block;
5
+ }
6
+
7
+ .rating {
8
+ display: inline-flex;
9
+ align-items: center;
10
+ gap: 0.15rem;
11
+ font-size: 1.2rem;
12
+ line-height: 1;
13
+ }
14
+
15
+ .star {
16
+ border: none;
17
+ background: transparent;
18
+ padding: 0;
19
+ margin: 0;
20
+ cursor: default;
21
+ color: var(--rating-empty);
22
+ user-select: none;
23
+ font-size: inherit;
24
+ }
25
+
26
+ .interactive .star {
27
+ cursor: pointer;
28
+ }
29
+
30
+ .star.filled {
31
+ color: var(--rating-filled);
32
+ }
33
+
34
+ button.star {
35
+ cursor: pointer;
36
+ }