recipe-planner-ui 1.1.0 → 1.2.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.
- package/dist/cjs/{index-B6uIqnrk.js → index-Cul1A0BY.js} +33 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/recipe-planner-ui.cjs.js +2 -2
- package/dist/cjs/rp-day-slot.cjs.entry.js +77 -9
- package/dist/cjs/rp-filter-chips_5.cjs.entry.js +49 -12
- package/dist/collection/components/rp-day-slot/rp-day-slot.css +191 -23
- package/dist/collection/components/rp-day-slot/rp-day-slot.js +83 -11
- package/dist/collection/components/rp-filter-chips/rp-filter-chips.css +35 -3
- package/dist/collection/components/rp-filter-chips/rp-filter-chips.js +1 -1
- package/dist/collection/components/rp-ingredient-list/rp-ingredient-list.css +39 -9
- package/dist/collection/components/rp-ingredient-list/rp-ingredient-list.js +2 -2
- package/dist/collection/components/rp-modal/rp-modal.css +65 -12
- package/dist/collection/components/rp-modal/rp-modal.js +1 -1
- package/dist/collection/components/rp-recipe-card/rp-recipe-card.css +165 -16
- package/dist/collection/components/rp-recipe-card/rp-recipe-card.js +83 -1
- package/dist/collection/components/rp-search-bar/rp-search-bar.css +100 -18
- package/dist/collection/components/rp-search-bar/rp-search-bar.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/rp-day-slot.js +1 -1
- package/dist/components/rp-filter-chips.js +1 -1
- package/dist/components/rp-ingredient-list.js +1 -1
- package/dist/components/rp-modal.js +1 -1
- package/dist/components/rp-recipe-card.js +1 -1
- package/dist/components/rp-search-bar.js +1 -1
- package/dist/esm/{index-B4wAFfci.js → index-BxP2u8bq.js} +33 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/recipe-planner-ui.js +3 -3
- package/dist/esm/rp-day-slot.entry.js +77 -9
- package/dist/esm/rp-filter-chips_5.entry.js +49 -12
- package/dist/recipe-planner-ui/p-1e3878fa.entry.js +1 -0
- package/dist/recipe-planner-ui/p-84819dee.entry.js +1 -0
- package/dist/recipe-planner-ui/p-BxP2u8bq.js +3 -0
- package/dist/recipe-planner-ui/recipe-planner-ui.css +6 -1
- package/dist/recipe-planner-ui/recipe-planner-ui.esm.js +1 -1
- package/dist/types/components/rp-day-slot/rp-day-slot.d.ts +22 -3
- package/dist/types/components/rp-recipe-card/rp-recipe-card.d.ts +20 -0
- package/dist/types/components.d.ts +35 -9
- package/package.json +1 -1
- package/dist/recipe-planner-ui/p-0c8f7438.entry.js +0 -1
- package/dist/recipe-planner-ui/p-B4wAFfci.js +0 -3
- package/dist/recipe-planner-ui/p-d54dbd37.entry.js +0 -1
|
@@ -591,6 +591,9 @@ var parsePropertyValue = (propValue, propType, isFormAssociated) => {
|
|
|
591
591
|
return propValue === "false" ? false : propValue === "" || !!propValue;
|
|
592
592
|
}
|
|
593
593
|
}
|
|
594
|
+
if (propType & 2 /* Number */) {
|
|
595
|
+
return typeof propValue === "string" ? parseFloat(propValue) : typeof propValue === "number" ? propValue : NaN;
|
|
596
|
+
}
|
|
594
597
|
if (propType & 1 /* String */) {
|
|
595
598
|
return String(propValue);
|
|
596
599
|
}
|
|
@@ -636,7 +639,11 @@ var setAccessor = (elm, memberName, oldValue, newValue, isSvg, flags, initialRen
|
|
|
636
639
|
classList.remove(...oldClasses.filter((c) => c && !newClasses.includes(c)));
|
|
637
640
|
classList.add(...newClasses.filter((c) => c && !oldClasses.includes(c)));
|
|
638
641
|
}
|
|
639
|
-
} else if (memberName === "key") ; else if (
|
|
642
|
+
} else if (memberName === "key") ; else if (memberName === "ref") {
|
|
643
|
+
if (newValue) {
|
|
644
|
+
queueRefAttachment(newValue, elm);
|
|
645
|
+
}
|
|
646
|
+
} else if ((!isProp ) && memberName[0] === "o" && memberName[1] === "n") {
|
|
640
647
|
if (memberName[2] === "-") {
|
|
641
648
|
memberName = memberName.slice(3);
|
|
642
649
|
} else if (isMemberInElement(win, ln)) {
|
|
@@ -780,6 +787,8 @@ var useNativeShadowDom = false;
|
|
|
780
787
|
var checkSlotFallbackVisibility = false;
|
|
781
788
|
var checkSlotRelocate = false;
|
|
782
789
|
var isSvgMode = false;
|
|
790
|
+
var refCallbacksToRemove = [];
|
|
791
|
+
var refCallbacksToAttach = [];
|
|
783
792
|
var createElm = (oldParentVNode, newParentVNode, childIndex) => {
|
|
784
793
|
var _a;
|
|
785
794
|
const newVNode2 = newParentVNode.$children$[childIndex];
|
|
@@ -932,6 +941,7 @@ var removeVnodes = (vnodes, startIdx, endIdx) => {
|
|
|
932
941
|
const vnode = vnodes[index];
|
|
933
942
|
if (vnode) {
|
|
934
943
|
const elm = vnode.$elm$;
|
|
944
|
+
nullifyVNodeRefs(vnode);
|
|
935
945
|
if (elm) {
|
|
936
946
|
{
|
|
937
947
|
checkSlotFallbackVisibility = true;
|
|
@@ -1152,6 +1162,27 @@ var markSlotContentForRelocation = (elm) => {
|
|
|
1152
1162
|
}
|
|
1153
1163
|
}
|
|
1154
1164
|
};
|
|
1165
|
+
var nullifyVNodeRefs = (vNode) => {
|
|
1166
|
+
{
|
|
1167
|
+
if (vNode.$attrs$ && vNode.$attrs$.ref) {
|
|
1168
|
+
refCallbacksToRemove.push(() => vNode.$attrs$.ref(null));
|
|
1169
|
+
}
|
|
1170
|
+
vNode.$children$ && vNode.$children$.map(nullifyVNodeRefs);
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
var queueRefAttachment = (refCallback, elm) => {
|
|
1174
|
+
{
|
|
1175
|
+
refCallbacksToAttach.push(() => refCallback(elm));
|
|
1176
|
+
}
|
|
1177
|
+
};
|
|
1178
|
+
var flushQueuedRefCallbacks = () => {
|
|
1179
|
+
{
|
|
1180
|
+
refCallbacksToRemove.forEach((cb) => cb());
|
|
1181
|
+
refCallbacksToRemove.length = 0;
|
|
1182
|
+
refCallbacksToAttach.forEach((cb) => cb());
|
|
1183
|
+
refCallbacksToAttach.length = 0;
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1155
1186
|
var insertBefore = (parent, newNode, reference, isInitialLoad) => {
|
|
1156
1187
|
{
|
|
1157
1188
|
if (typeof newNode["s-sn"] === "string" && !!newNode["s-sr"] && !!newNode["s-cr"]) {
|
|
@@ -1321,6 +1352,7 @@ var renderVdom = (hostRef, renderFnResults, isInitialLoad = false) => {
|
|
|
1321
1352
|
}
|
|
1322
1353
|
}
|
|
1323
1354
|
contentRef = void 0;
|
|
1355
|
+
flushQueuedRefCallbacks();
|
|
1324
1356
|
};
|
|
1325
1357
|
|
|
1326
1358
|
// src/runtime/update-component.ts
|
package/dist/cjs/loader.cjs.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-Cul1A0BY.js');
|
|
4
4
|
var appGlobals = require('./app-globals-V2Kpy_OQ.js');
|
|
5
5
|
|
|
6
6
|
const defineCustomElements = async (win, options) => {
|
|
7
7
|
if (typeof window === 'undefined') return undefined;
|
|
8
8
|
await appGlobals.globalScripts();
|
|
9
|
-
return index.bootstrapLazy([["rp-filter-chips_5.cjs",[[514,"rp-filter-chips",{"options":[16],"selected":[1],"label":[1]}],[774,"rp-ingredient-list",{"items":[16]}],[774,"rp-modal",{"open":[516],"heading":[1],"focusFirstField":[64]},null,{"open":[{"onOpenChange":0}]}],[774,"rp-recipe-card",{"recipeId":[1,"recipe-id"],"recipeTitle":[1,"recipe-title"],"image":[1],"category":[1],"favorite":[516]}],[514,"rp-search-bar",{"value":[1],"placeholder":[1],"label":[1],"draft":[32]},null,{"value":[{"onValueChange":0}]}]]],["rp-day-slot.cjs",[[774,"rp-day-slot",{"day":[1],"dayLabel":[1,"day-label"],"meals":[16],"days":[16],"dayLabels":[16],"normalized":[32]}]]]], options);
|
|
9
|
+
return index.bootstrapLazy([["rp-filter-chips_5.cjs",[[514,"rp-filter-chips",{"options":[16],"selected":[1],"label":[1]}],[774,"rp-ingredient-list",{"items":[16]}],[774,"rp-modal",{"open":[516],"heading":[1],"focusFirstField":[64]},null,{"open":[{"onOpenChange":0}]}],[774,"rp-recipe-card",{"recipeId":[1,"recipe-id"],"recipeTitle":[1,"recipe-title"],"image":[1],"category":[1],"area":[1],"minutes":[2],"favorite":[516],"imageLoading":[32],"imageFailed":[32],"pulsing":[32]}],[514,"rp-search-bar",{"value":[1],"placeholder":[1],"label":[1],"draft":[32]},null,{"value":[{"onValueChange":0}]}]]],["rp-day-slot.cjs",[[774,"rp-day-slot",{"day":[1],"dayLabel":[1,"day-label"],"meals":[16],"days":[16],"dayLabels":[16],"normalized":[32],"dropActive":[32],"draggingId":[32]}]]]], options);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
exports.setNonce = index.setNonce;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-Cul1A0BY.js');
|
|
4
4
|
var appGlobals = require('./app-globals-V2Kpy_OQ.js');
|
|
5
5
|
|
|
6
6
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -19,7 +19,7 @@ var patchBrowser = () => {
|
|
|
19
19
|
|
|
20
20
|
patchBrowser().then(async (options) => {
|
|
21
21
|
await appGlobals.globalScripts();
|
|
22
|
-
return index.bootstrapLazy([["rp-filter-chips_5.cjs",[[514,"rp-filter-chips",{"options":[16],"selected":[1],"label":[1]}],[774,"rp-ingredient-list",{"items":[16]}],[774,"rp-modal",{"open":[516],"heading":[1],"focusFirstField":[64]},null,{"open":[{"onOpenChange":0}]}],[774,"rp-recipe-card",{"recipeId":[1,"recipe-id"],"recipeTitle":[1,"recipe-title"],"image":[1],"category":[1],"favorite":[516]}],[514,"rp-search-bar",{"value":[1],"placeholder":[1],"label":[1],"draft":[32]},null,{"value":[{"onValueChange":0}]}]]],["rp-day-slot.cjs",[[774,"rp-day-slot",{"day":[1],"dayLabel":[1,"day-label"],"meals":[16],"days":[16],"dayLabels":[16],"normalized":[32]}]]]], options);
|
|
22
|
+
return index.bootstrapLazy([["rp-filter-chips_5.cjs",[[514,"rp-filter-chips",{"options":[16],"selected":[1],"label":[1]}],[774,"rp-ingredient-list",{"items":[16]}],[774,"rp-modal",{"open":[516],"heading":[1],"focusFirstField":[64]},null,{"open":[{"onOpenChange":0}]}],[774,"rp-recipe-card",{"recipeId":[1,"recipe-id"],"recipeTitle":[1,"recipe-title"],"image":[1],"category":[1],"area":[1],"minutes":[2],"favorite":[516],"imageLoading":[32],"imageFailed":[32],"pulsing":[32]}],[514,"rp-search-bar",{"value":[1],"placeholder":[1],"label":[1],"draft":[32]},null,{"value":[{"onValueChange":0}]}]]],["rp-day-slot.cjs",[[774,"rp-day-slot",{"day":[1],"dayLabel":[1,"day-label"],"meals":[16],"days":[16],"dayLabels":[16],"normalized":[32],"dropActive":[32],"draggingId":[32]}]]]], options);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
exports.setNonce = index.setNonce;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-Cul1A0BY.js');
|
|
4
4
|
|
|
5
|
-
const rpDaySlotCss = () => `.sc-rp-day-slot-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.slot.sc-rp-day-slot{display:flex;flex-direction:column;height:100%;min-height:
|
|
5
|
+
const rpDaySlotCss = () => `.sc-rp-day-slot-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.slot.sc-rp-day-slot{display:flex;flex-direction:column;height:100%;min-height:200px;overflow:hidden;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-xs);transition:border-color var(--rp-duration) var(--rp-ease), box-shadow var(--rp-duration) var(--rp-ease), background-color var(--rp-duration) var(--rp-ease)}.slot.is-empty.sc-rp-day-slot{background:var(--rp-color-surface-sunken);border-style:dashed}.slot.is-drop-active.sc-rp-day-slot{background:var(--rp-color-highlight-soft);border-style:solid;border-color:var(--rp-color-highlight);box-shadow:var(--rp-shadow-md), inset 0 0 0 1px var(--rp-color-highlight)}.head.sc-rp-day-slot{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;padding:var(--rp-space-3);border-bottom:1px solid var(--rp-color-border)}.day.sc-rp-day-slot{min-width:0;margin:0;overflow:hidden;font-size:var(--rp-font-size-xs);font-weight:700;letter-spacing:0.08em;text-transform:uppercase;text-overflow:ellipsis;white-space:nowrap;color:var(--rp-color-text-muted)}.head-right.sc-rp-day-slot{display:flex;flex-shrink:0;gap:var(--rp-space-2);align-items:center}.count.sc-rp-day-slot{display:grid;place-items:center;min-width:20px;height:20px;padding:0 6px;font-size:0.6875rem;font-weight:700;font-variant-numeric:tabular-nums;color:var(--rp-caramel-600);background:var(--rp-color-highlight-soft);border-radius:var(--rp-radius-pill)}.add.sc-rp-day-slot{display:grid;place-items:center;width:26px;height:26px;padding:0;cursor:pointer;color:var(--rp-color-accent-contrast);background:var(--rp-color-accent);border:none;border-radius:50%;transition:transform var(--rp-duration-fast) var(--rp-ease), background-color var(--rp-duration-fast) var(--rp-ease)}.add.sc-rp-day-slot svg.sc-rp-day-slot{fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}.add.sc-rp-day-slot:hover{background:var(--rp-color-highlight);transform:rotate(90deg) scale(1.1)}.add.sc-rp-day-slot:active{transform:rotate(90deg) scale(0.92)}.meals.sc-rp-day-slot{flex:1;margin:0;padding:var(--rp-space-2);list-style:none;display:flex;flex-direction:column;gap:var(--rp-space-2)}.meal.sc-rp-day-slot{position:relative;padding:var(--rp-space-3) var(--rp-space-3) var(--rp-space-2);cursor:grab;background:var(--rp-color-surface-sunken);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-md);transition:transform var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease), opacity var(--rp-duration-fast) var(--rp-ease)}.meal.sc-rp-day-slot:hover{background:var(--rp-color-surface);box-shadow:var(--rp-shadow-sm);transform:translateY(-1px)}.meal.sc-rp-day-slot:active{cursor:grabbing}.meal.is-dragging.sc-rp-day-slot{opacity:0.4;box-shadow:none;transform:none}.grip.sc-rp-day-slot{position:absolute;inset-block-start:var(--rp-space-2);inset-inline-end:var(--rp-space-2);display:block;opacity:0;transition:opacity var(--rp-duration-fast) var(--rp-ease)}.grip.sc-rp-day-slot svg.sc-rp-day-slot{display:block;fill:var(--rp-color-text-subtle)}.meal.sc-rp-day-slot:hover .grip.sc-rp-day-slot{opacity:1}.meal-title.sc-rp-day-slot{display:block;padding-inline-end:var(--rp-space-4);font-size:var(--rp-font-size-sm);font-weight:500;line-height:1.35;color:var(--rp-color-text)}.meal-actions.sc-rp-day-slot{display:flex;gap:var(--rp-space-1);align-items:center;justify-content:space-between;margin-top:var(--rp-space-2)}.move-select.sc-rp-day-slot{max-width:100%;padding:3px var(--rp-space-2);font:inherit;font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-sm);transition:border-color var(--rp-duration-fast) var(--rp-ease)}.move-select.sc-rp-day-slot:hover{border-color:var(--rp-color-border-strong)}.remove.sc-rp-day-slot{display:grid;place-items:center;width:24px;height:24px;padding:0;color:var(--rp-color-text-subtle);cursor:pointer;background:none;border:none;border-radius:var(--rp-radius-sm);transition:color var(--rp-duration-fast) var(--rp-ease), background-color var(--rp-duration-fast) var(--rp-ease)}.remove.sc-rp-day-slot svg.sc-rp-day-slot{fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}.remove.sc-rp-day-slot:hover{color:var(--rp-color-danger);background:var(--rp-color-danger-soft)}.empty.sc-rp-day-slot{display:flex;flex:1;flex-direction:column;gap:var(--rp-space-2);align-items:center;justify-content:center;padding:var(--rp-space-4) var(--rp-space-3);text-align:center}.empty-icon.sc-rp-day-slot{fill:none;stroke:var(--rp-color-text-subtle);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}.empty-text.sc-rp-day-slot{margin:0;font-size:var(--rp-font-size-xs);color:var(--rp-color-text-subtle)}.add.sc-rp-day-slot:focus-visible,.remove.sc-rp-day-slot:focus-visible,.move-select.sc-rp-day-slot:focus-visible{outline:var(--rp-focus-ring);outline-offset:var(--rp-focus-offset)}.sr-only.sc-rp-day-slot{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media (prefers-reduced-motion: reduce){.slot.sc-rp-day-slot,.meal.sc-rp-day-slot,.add.sc-rp-day-slot,.grip.sc-rp-day-slot,.remove.sc-rp-day-slot,.move-select.sc-rp-day-slot{transition:none}.meal.sc-rp-day-slot:hover,.add.sc-rp-day-slot:hover,.add.sc-rp-day-slot:active{transform:none}.grip.sc-rp-day-slot{opacity:1}}`;
|
|
6
6
|
|
|
7
7
|
const DaySlot = class {
|
|
8
8
|
constructor(hostRef) {
|
|
@@ -27,11 +27,20 @@ const DaySlot = class {
|
|
|
27
27
|
*/
|
|
28
28
|
dayLabels = {};
|
|
29
29
|
normalized = [];
|
|
30
|
+
/** True while a compatible meal is being dragged over this column. */
|
|
31
|
+
dropActive = false;
|
|
32
|
+
/** Id of the meal being dragged out of this column, dimmed at its origin. */
|
|
33
|
+
draggingId = null;
|
|
34
|
+
/**
|
|
35
|
+
* Nested children fire dragleave as the pointer crosses them, so a boolean flag would
|
|
36
|
+
* flicker off mid-column. Counting enter and leave pairs is what makes the state stable.
|
|
37
|
+
*/
|
|
38
|
+
dragDepth = 0;
|
|
30
39
|
/** Fired when the user asks to add a meal to this day. */
|
|
31
40
|
rpAddMeal;
|
|
32
41
|
/** Fired when a meal is removed from this day. */
|
|
33
42
|
rpRemoveMeal;
|
|
34
|
-
/** Fired when a meal is reassigned to a different day. */
|
|
43
|
+
/** Fired when a meal is reassigned to a different day, by drag or by select. */
|
|
35
44
|
rpMoveMeal;
|
|
36
45
|
componentWillLoad() {
|
|
37
46
|
this.normalized = Array.isArray(this.meals) ? this.meals : [];
|
|
@@ -41,23 +50,82 @@ const DaySlot = class {
|
|
|
41
50
|
// replaced before the element upgrades, which @Watch would miss.
|
|
42
51
|
this.normalized = Array.isArray(this.meals) ? this.meals : [];
|
|
43
52
|
}
|
|
53
|
+
emitMove(id, from, to) {
|
|
54
|
+
if (!to || to === from)
|
|
55
|
+
return;
|
|
56
|
+
this.rpMoveMeal.emit({ id, from, to });
|
|
57
|
+
}
|
|
44
58
|
onMove = (event, meal) => {
|
|
45
59
|
const select = event.target;
|
|
46
|
-
|
|
47
|
-
if (!to || to === this.day)
|
|
48
|
-
return;
|
|
49
|
-
this.rpMoveMeal.emit({ id: meal.id, from: this.day, to });
|
|
60
|
+
this.emitMove(meal.id, this.day, select.value);
|
|
50
61
|
// The consumer re-renders from its own data; resetting avoids a stale selection
|
|
51
62
|
// if that render is delayed.
|
|
52
63
|
select.value = '';
|
|
53
64
|
};
|
|
65
|
+
onDragStart = (event, meal) => {
|
|
66
|
+
this.draggingId = meal.id;
|
|
67
|
+
// A custom MIME type is what lets dragover distinguish a meal from a dragged file or
|
|
68
|
+
// a text selection, so unrelated drags never light up a column as a drop target.
|
|
69
|
+
event.dataTransfer?.setData('application/x-rp-meal', JSON.stringify({ id: meal.id, from: this.day }));
|
|
70
|
+
// text/plain is set alongside it because some browsers refuse a drag with no
|
|
71
|
+
// conventional format attached.
|
|
72
|
+
event.dataTransfer?.setData('text/plain', meal.title);
|
|
73
|
+
if (event.dataTransfer)
|
|
74
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
75
|
+
};
|
|
76
|
+
onDragEnd = () => {
|
|
77
|
+
this.draggingId = null;
|
|
78
|
+
this.dragDepth = 0;
|
|
79
|
+
this.dropActive = false;
|
|
80
|
+
};
|
|
81
|
+
hasMealPayload(event) {
|
|
82
|
+
return event.dataTransfer?.types.includes('application/x-rp-meal') ?? false;
|
|
83
|
+
}
|
|
84
|
+
onDragEnter = (event) => {
|
|
85
|
+
if (!this.hasMealPayload(event))
|
|
86
|
+
return;
|
|
87
|
+
this.dragDepth += 1;
|
|
88
|
+
this.dropActive = true;
|
|
89
|
+
};
|
|
90
|
+
onDragOver = (event) => {
|
|
91
|
+
if (!this.hasMealPayload(event))
|
|
92
|
+
return;
|
|
93
|
+
// Without preventDefault the browser treats the element as a non-drop zone and the
|
|
94
|
+
// drop event never fires.
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
if (event.dataTransfer)
|
|
97
|
+
event.dataTransfer.dropEffect = 'move';
|
|
98
|
+
};
|
|
99
|
+
onDragLeave = (event) => {
|
|
100
|
+
if (!this.hasMealPayload(event))
|
|
101
|
+
return;
|
|
102
|
+
this.dragDepth = Math.max(0, this.dragDepth - 1);
|
|
103
|
+
if (this.dragDepth === 0)
|
|
104
|
+
this.dropActive = false;
|
|
105
|
+
};
|
|
106
|
+
onDrop = (event) => {
|
|
107
|
+
const payload = event.dataTransfer?.getData('application/x-rp-meal');
|
|
108
|
+
if (!payload)
|
|
109
|
+
return;
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
this.dragDepth = 0;
|
|
112
|
+
this.dropActive = false;
|
|
113
|
+
try {
|
|
114
|
+
const { id, from } = JSON.parse(payload);
|
|
115
|
+
this.emitMove(id, from, this.day);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// A malformed payload means the drag did not originate here; ignoring it is
|
|
119
|
+
// preferable to throwing inside a drop handler, where nothing would catch it.
|
|
120
|
+
}
|
|
121
|
+
};
|
|
54
122
|
render() {
|
|
55
123
|
const days = Array.isArray(this.days) ? this.days : [];
|
|
56
124
|
const labels = this.dayLabels ?? {};
|
|
57
125
|
const meals = this.normalized;
|
|
58
|
-
return (index.h(index.Host, { key: '
|
|
126
|
+
return (index.h(index.Host, { key: '755cdc190abccb9b0350caf7e4fad05675dd6e0e' }, index.h("section", { key: '927c1e962ce3f918e001965da10bb39b82cab5bc', class: { slot: true, 'is-drop-active': this.dropActive, 'is-empty': meals.length === 0 }, onDragEnter: this.onDragEnter, onDragOver: this.onDragOver, onDragLeave: this.onDragLeave, onDrop: this.onDrop }, index.h("header", { key: '415e9d56f9b190fd291af942c01427cc4b9b66ea', class: "head" }, index.h("h3", { key: 'd0f20de86c70d85da545ec9ec9c57790961b78f0', class: "day" }, this.dayLabel || this.day), index.h("div", { key: '484a1e743a3f251865288f345ead14d87741ff8e', class: "head-right" }, meals.length > 0 && index.h("span", { key: 'ac3324168f0061f4bb173090e21c4b6f2334a168', class: "count" }, meals.length), index.h("button", { key: '5ca123821d1b90cc822bb3036884ce93f8cae19c', type: "button", class: "add", onClick: () => this.rpAddMeal.emit(this.day), "aria-label": `Add a meal to ${this.dayLabel || this.day}` }, index.h("svg", { key: 'e7b09c139cfd3106a83481a1bbb48bf99e82d47c', viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, index.h("path", { key: '06c62bb2b09a4c0676977411644d15d4217361a8', d: "M12 5v14M5 12h14" }))))), meals.length === 0 ? (index.h("div", { class: "empty" }, index.h("slot", null, index.h("svg", { class: "empty-icon", viewBox: "0 0 24 24", width: "26", height: "26", "aria-hidden": "true" }, index.h("path", { d: "M4 4h16v16H4z", opacity: "0.35" }), index.h("path", { d: "M8 2v4M16 2v4M4 10h16" })), index.h("p", { class: "empty-text" }, "No meals planned")))) : (index.h("ul", { class: "meals" }, meals.map((meal) => (index.h("li", { class: { meal: true, 'is-dragging': this.draggingId === meal.id }, key: meal.id, draggable: true, onDragStart: (event) => this.onDragStart(event, meal), onDragEnd: this.onDragEnd }, index.h("span", { class: "grip", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", width: "12", height: "12" }, index.h("circle", { cx: "9", cy: "6", r: "1.4" }), index.h("circle", { cx: "15", cy: "6", r: "1.4" }), index.h("circle", { cx: "9", cy: "12", r: "1.4" }), index.h("circle", { cx: "15", cy: "12", r: "1.4" }), index.h("circle", { cx: "9", cy: "18", r: "1.4" }), index.h("circle", { cx: "15", cy: "18", r: "1.4" }))), index.h("span", { class: "meal-title" }, meal.title), index.h("div", { class: "meal-actions" }, index.h("label", { class: "move" }, index.h("span", { class: "sr-only" }, `Move ${meal.title} to another day`), index.h("select", { class: "move-select", onChange: (event) => this.onMove(event, meal) }, index.h("option", { value: "" }, "Move\u2026"), days
|
|
59
127
|
.filter((day) => day !== this.day)
|
|
60
|
-
.map((day) => (index.h("option", { key: day, value: day }, labels[day] ?? day))))), index.h("button", { type: "button", class: "remove", onClick: () => this.rpRemoveMeal.emit({ id: meal.id, day: this.day }), "aria-label": `Remove ${meal.title}` }, "
|
|
128
|
+
.map((day) => (index.h("option", { key: day, value: day }, labels[day] ?? day))))), index.h("button", { type: "button", class: "remove", onClick: () => this.rpRemoveMeal.emit({ id: meal.id, day: this.day }), "aria-label": `Remove ${meal.title}` }, index.h("svg", { viewBox: "0 0 24 24", width: "13", height: "13", "aria-hidden": "true" }, index.h("path", { d: "M6 6l12 12M18 6L6 18" }))))))))))));
|
|
61
129
|
}
|
|
62
130
|
};
|
|
63
131
|
DaySlot.style = rpDaySlotCss();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-Cul1A0BY.js');
|
|
4
4
|
|
|
5
|
-
const rpFilterChipsCss = () => `.sc-rp-filter-chips-h{display:block;font-family:var(--rp-font-sans)}.chips.sc-rp-filter-chips{display:flex;flex-wrap:wrap;gap:var(--rp-space-2)}.chip.sc-rp-filter-chips{padding:
|
|
5
|
+
const rpFilterChipsCss = () => `.sc-rp-filter-chips-h{display:block;font-family:var(--rp-font-sans)}.chips.sc-rp-filter-chips{display:flex;flex-wrap:wrap;gap:var(--rp-space-2)}.chip.sc-rp-filter-chips{padding:6px var(--rp-space-4);font:inherit;font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-body);cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-pill);transition:color var(--rp-duration-fast) var(--rp-ease), background-color var(--rp-duration-fast) var(--rp-ease), border-color var(--rp-duration-fast) var(--rp-ease), transform var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.chip.sc-rp-filter-chips:hover{color:var(--rp-color-text);background:var(--rp-color-surface-sunken);border-color:var(--rp-color-border-strong);transform:translateY(-1px)}.chip.sc-rp-filter-chips:active{transform:translateY(0) scale(0.97)}.chip.is-selected.sc-rp-filter-chips{color:var(--rp-color-accent-contrast);background:var(--rp-color-accent);border-color:var(--rp-color-accent);box-shadow:var(--rp-shadow-sm)}.chip.is-selected.sc-rp-filter-chips:hover{color:var(--rp-color-accent-contrast);background:var(--rp-color-accent-hover);border-color:var(--rp-color-accent-hover)}.chip.sc-rp-filter-chips:focus-visible{outline:var(--rp-focus-ring);outline-offset:var(--rp-focus-offset)}@media (prefers-reduced-motion: reduce){.chip.sc-rp-filter-chips{transition:none}.chip.sc-rp-filter-chips:hover,.chip.sc-rp-filter-chips:active{transform:none}}`;
|
|
6
6
|
|
|
7
7
|
const FilterChips = class {
|
|
8
8
|
constructor(hostRef) {
|
|
@@ -29,12 +29,12 @@ const FilterChips = class {
|
|
|
29
29
|
// A string prop arriving from an HTML attribute would be unusable; tolerate it so
|
|
30
30
|
// the component behaves predictably in a plain .html page.
|
|
31
31
|
const options = Array.isArray(this.options) ? this.options : [];
|
|
32
|
-
return (index.h(index.Host, { key: '
|
|
32
|
+
return (index.h(index.Host, { key: 'f695ec8ae5603061f1fcf027257563c416f8fde8' }, index.h("div", { key: '80b59e2aaedd649ec387534da5dd3dc5d9955be5', class: "chips", role: "group", "aria-label": this.label }, options.map((option) => (index.h("button", { key: option, type: "button", class: { chip: true, 'is-selected': this.selected === option }, "aria-pressed": String(this.selected === option), onClick: () => this.select(option) }, option))))));
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
FilterChips.style = rpFilterChipsCss();
|
|
36
36
|
|
|
37
|
-
const rpIngredientListCss = () => `.sc-rp-ingredient-list-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.heading.sc-rp-ingredient-list{margin:0 0 var(--rp-space-
|
|
37
|
+
const rpIngredientListCss = () => `.sc-rp-ingredient-list-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.heading.sc-rp-ingredient-list{margin:0 0 var(--rp-space-4);font-family:var(--rp-font-serif);font-size:var(--rp-font-size-xl);font-weight:600;letter-spacing:-0.015em}.list.sc-rp-ingredient-list{margin:0;padding:var(--rp-space-2);list-style:none;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-xs);overflow:hidden}.row.sc-rp-ingredient-list{display:flex;justify-content:space-between;gap:var(--rp-space-4);padding:var(--rp-space-3);font-size:var(--rp-font-size-md);border-radius:var(--rp-radius-sm);transition:background-color var(--rp-duration-fast) var(--rp-ease)}.row.sc-rp-ingredient-list:hover{background:var(--rp-color-highlight-soft)}.name.sc-rp-ingredient-list{color:var(--rp-color-text-body)}.measure.sc-rp-ingredient-list{flex-shrink:0;font-size:var(--rp-font-size-sm);font-weight:600;color:var(--rp-caramel-600);font-variant-numeric:tabular-nums}.empty.sc-rp-ingredient-list{margin:0;padding:var(--rp-space-5);font-size:var(--rp-font-size-md);color:var(--rp-color-text-muted);text-align:center;background:var(--rp-color-surface-sunken);border:1px dashed var(--rp-color-border-strong);border-radius:var(--rp-radius-lg)}.note.sc-rp-ingredient-list{margin-top:var(--rp-space-3);font-size:var(--rp-font-size-sm);color:var(--rp-color-text-muted);text-align:center}.note.sc-rp-ingredient-list:not(:has(*)){display:none}@media (prefers-reduced-motion: reduce){.row.sc-rp-ingredient-list{transition:none}}`;
|
|
38
38
|
|
|
39
39
|
const IngredientList = class {
|
|
40
40
|
constructor(hostRef) {
|
|
@@ -44,15 +44,15 @@ const IngredientList = class {
|
|
|
44
44
|
items = [];
|
|
45
45
|
render() {
|
|
46
46
|
const items = Array.isArray(this.items) ? this.items : [];
|
|
47
|
-
return (index.h(index.Host, { key: '
|
|
47
|
+
return (index.h(index.Host, { key: '908db0a9d14068fff426be9e86908c67295ef413' }, index.h("section", { key: '28f9022e75e767ba85a2f9fcfaa23f6a14d83576', class: "wrap" }, index.h("slot", { key: '0909fca0976d34c2e5ccbc7c935bc7b1148480ec', name: "heading" }, index.h("h2", { key: '61922c8539936be7bfcbbd27d658ef0085b19c80', class: "heading" }, "Ingredients")), items.length === 0 ? (index.h("p", { class: "empty" }, "No ingredients listed for this recipe.")) : (index.h("ul", { class: "list" }, items.map((item, index$1) => (
|
|
48
48
|
// Ingredient names repeat within a recipe (for example, oil listed twice
|
|
49
49
|
// with different measures), so the index is part of the identity.
|
|
50
|
-
index.h("li", { class: "row", key: `${item.name}-${index$1}` }, index.h("span", { class: "name" }, item.name), index.h("span", { class: "measure" }, item.measure)))))), index.h("div", { key: '
|
|
50
|
+
index.h("li", { class: "row", key: `${item.name}-${index$1}` }, index.h("span", { class: "name" }, item.name), index.h("span", { class: "measure" }, item.measure)))))), index.h("div", { key: 'e394fb29b9484d890dba642c6079e10621550843', class: "note" }, index.h("slot", { key: '92269d3f3158ae3a1f1ea8b86a37d2b1a66da069' })))));
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
IngredientList.style = rpIngredientListCss();
|
|
54
54
|
|
|
55
|
-
const rpModalCss = () => `.sc-rp-modal-h{display:contents;font-family:var(--rp-font-sans)}.backdrop.sc-rp-modal{position:fixed;inset:0;z-index:100;display:grid;place-items:center;padding:var(--rp-space-4);background:rgb(
|
|
55
|
+
const rpModalCss = () => `.sc-rp-modal-h{display:contents;font-family:var(--rp-font-sans)}.sc-rp-modal-h:not([open]){display:none}.backdrop.sc-rp-modal{position:fixed;inset:0;z-index:100;display:grid;place-items:center;padding:var(--rp-space-4);background:rgb(44 24 16 / 0.42);backdrop-filter:blur(6px)}.dialog.sc-rp-modal{display:flex;flex-direction:column;width:min(560px, 100%);max-height:min(80vh, 640px);overflow:hidden;color:var(--rp-color-text);background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-xl);box-shadow:var(--rp-shadow-xl)}.head.sc-rp-modal{display:flex;gap:var(--rp-space-3);align-items:center;justify-content:space-between;padding:var(--rp-space-5) var(--rp-space-5) var(--rp-space-4);border-bottom:1px solid var(--rp-color-border)}.heading.sc-rp-modal{margin:0;font-family:var(--rp-font-serif);font-size:var(--rp-font-size-xl);font-weight:600;letter-spacing:-0.015em}.close.sc-rp-modal{display:grid;place-items:center;flex-shrink:0;width:32px;height:32px;padding:0;color:var(--rp-color-text-muted);cursor:pointer;background:none;border:none;border-radius:50%;transition:color var(--rp-duration-fast) var(--rp-ease), background-color var(--rp-duration-fast) var(--rp-ease), transform var(--rp-duration-fast) var(--rp-ease)}.close.sc-rp-modal svg.sc-rp-modal{fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}.close.sc-rp-modal:hover{color:var(--rp-color-text);background:var(--rp-color-surface-sunken);transform:rotate(90deg)}.close.sc-rp-modal:focus-visible{outline:var(--rp-focus-ring);outline-offset:var(--rp-focus-offset)}.body.sc-rp-modal{flex:1;padding:var(--rp-space-5);font-size:var(--rp-font-size-md);color:var(--rp-color-text-body);overflow-y:auto}.foot.sc-rp-modal{display:flex;gap:var(--rp-space-2);justify-content:flex-end;padding:var(--rp-space-4) var(--rp-space-5) var(--rp-space-5);background:var(--rp-color-surface-sunken);border-top:1px solid var(--rp-color-border)}.foot.sc-rp-modal:not(:has(*)){display:none}@media (prefers-reduced-motion: no-preference){.backdrop.sc-rp-modal{animation:rp-backdrop-in var(--rp-duration) var(--rp-ease)}.dialog.sc-rp-modal{animation:rp-modal-in var(--rp-duration) var(--rp-ease)}@keyframes rp-backdrop-in{from{opacity:0}}@keyframes rp-modal-in{from{opacity:0;transform:translateY(12px) scale(0.97)}}}@media (prefers-reduced-motion: reduce){.close.sc-rp-modal{transition:none}.close.sc-rp-modal:hover{transform:none}}`;
|
|
56
56
|
|
|
57
57
|
const FOCUSABLE = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
58
58
|
const Modal = class {
|
|
@@ -135,7 +135,7 @@ const Modal = class {
|
|
|
135
135
|
render() {
|
|
136
136
|
if (!this.open)
|
|
137
137
|
return null;
|
|
138
|
-
return (index.h(index.Host, null, index.h("div", { class: "backdrop", onClick: this.onBackdropClick }, index.h("div", { class: "dialog", role: "dialog", "aria-modal": "true", "aria-label": this.heading }, index.h("header", { class: "head" }, index.h("h2", { class: "heading" }, this.heading), index.h("button", { type: "button", class: "close", onClick: () => this.rpClose.emit(), "aria-label": "Close dialog" }, "
|
|
138
|
+
return (index.h(index.Host, null, index.h("div", { class: "backdrop", onClick: this.onBackdropClick }, index.h("div", { class: "dialog", role: "dialog", "aria-modal": "true", "aria-label": this.heading }, index.h("header", { class: "head" }, index.h("h2", { class: "heading" }, this.heading), index.h("button", { type: "button", class: "close", onClick: () => this.rpClose.emit(), "aria-label": "Close dialog" }, index.h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, index.h("path", { d: "M6 6l12 12M18 6L6 18" })))), index.h("div", { class: "body" }, index.h("slot", null)), index.h("footer", { class: "foot" }, index.h("slot", { name: "footer" }))))));
|
|
139
139
|
}
|
|
140
140
|
static get watchers() { return {
|
|
141
141
|
"open": [{
|
|
@@ -145,7 +145,7 @@ const Modal = class {
|
|
|
145
145
|
};
|
|
146
146
|
Modal.style = rpModalCss();
|
|
147
147
|
|
|
148
|
-
const rpRecipeCardCss = () => `.sc-rp-recipe-card-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.card.sc-rp-recipe-card{display:flex;flex-direction:column;height:100%;overflow:hidden;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-sm)}.media.sc-rp-recipe-card{position:relative;aspect-ratio:4 / 3;background:var(--rp-color-surface-sunken)}.media.sc-rp-recipe-card img.sc-rp-recipe-card{display:block;width:100%;height:100%;object-fit:cover}.media-fallback.sc-rp-recipe-card{width:100%;height:100%;background:linear-gradient(135deg, var(--rp-
|
|
148
|
+
const rpRecipeCardCss = () => `.sc-rp-recipe-card-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.card.sc-rp-recipe-card{display:flex;flex-direction:column;height:100%;overflow:hidden;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-sm);transition:transform var(--rp-duration) var(--rp-ease), box-shadow var(--rp-duration) var(--rp-ease), border-color var(--rp-duration) var(--rp-ease)}.sc-rp-recipe-card-h:hover .card.sc-rp-recipe-card{border-color:var(--rp-color-border-strong);box-shadow:var(--rp-shadow-lg);transform:translateY(-4px)}.media.sc-rp-recipe-card{position:relative;aspect-ratio:4 / 3;overflow:hidden;background:var(--rp-color-surface-sunken)}.media.sc-rp-recipe-card img.sc-rp-recipe-card{display:block;width:100%;height:100%;object-fit:cover;transition:transform var(--rp-duration-slow) var(--rp-ease), opacity var(--rp-duration) var(--rp-ease)}.sc-rp-recipe-card-h:hover .media.sc-rp-recipe-card img.sc-rp-recipe-card{transform:scale(1.04)}.media.is-loading.sc-rp-recipe-card img.sc-rp-recipe-card{opacity:0}.media-fallback.sc-rp-recipe-card{width:100%;height:100%;background:radial-gradient(circle at 30% 25%, rgb(255 255 255 / 0.55), transparent 55%), linear-gradient(135deg, var(--rp-caramel-100), var(--rp-cream-400))}.scrim.sc-rp-recipe-card{position:absolute;inset:0;pointer-events:none;background:linear-gradient(to bottom, rgb(44 24 16 / 0.18) 0%, transparent 34%)}.badges.sc-rp-recipe-card{position:absolute;inset-block-start:var(--rp-space-3);inset-inline-start:var(--rp-space-3);display:flex;flex-wrap:wrap;gap:var(--rp-space-1)}.favorite.sc-rp-recipe-card{position:absolute;inset-block-start:var(--rp-space-3);inset-inline-end:var(--rp-space-3);display:grid;place-items:center;width:36px;height:36px;padding:0;cursor:pointer;background:rgb(255 255 255 / 0.82);backdrop-filter:blur(8px);border:1px solid rgb(255 255 255 / 0.6);border-radius:50%;box-shadow:var(--rp-shadow-sm);transition:transform var(--rp-duration-fast) var(--rp-ease), background-color var(--rp-duration-fast) var(--rp-ease)}.favorite.sc-rp-recipe-card:hover{background:var(--rp-color-surface);transform:scale(1.08)}.favorite.sc-rp-recipe-card:active{transform:scale(0.94)}.favorite.sc-rp-recipe-card svg.sc-rp-recipe-card{fill:none;stroke:var(--rp-espresso-800);stroke-width:1.9;stroke-linejoin:round;transition:fill var(--rp-duration-fast) var(--rp-ease), stroke var(--rp-duration-fast) var(--rp-ease)}[favorite].sc-rp-recipe-card-h .favorite.sc-rp-recipe-card svg.sc-rp-recipe-card{fill:var(--rp-color-favorite);stroke:var(--rp-color-favorite)}.favorite.sc-rp-recipe-card:focus-visible{outline:var(--rp-focus-ring);outline-offset:var(--rp-focus-offset)}.body.sc-rp-recipe-card{flex:1;padding:var(--rp-space-4) var(--rp-space-4) var(--rp-space-3)}.title.sc-rp-recipe-card{margin:0;font-family:var(--rp-font-serif);font-size:1.0625rem;font-weight:600;line-height:1.28;letter-spacing:-0.01em;color:var(--rp-color-text);display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden}.meta.sc-rp-recipe-card{display:flex;flex-wrap:wrap;gap:var(--rp-space-1);margin-top:var(--rp-space-3)}.pill.sc-rp-recipe-card{padding:3px 10px;font-size:var(--rp-font-size-xs);font-weight:500;letter-spacing:0.01em;color:var(--rp-color-text-muted);background:var(--rp-color-surface-sunken);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-pill);white-space:nowrap}.pill-category.sc-rp-recipe-card{color:var(--rp-caramel-600);background:var(--rp-color-highlight-soft);border-color:transparent}.actions.sc-rp-recipe-card{display:flex;gap:var(--rp-space-3);align-items:center;padding:0 var(--rp-space-4) var(--rp-space-4)}.actions.sc-rp-recipe-card:not(:has(*)){display:none}@media (prefers-reduced-motion: no-preference){.media.is-loading.sc-rp-recipe-card::after{content:'';position:absolute;inset:0;background:linear-gradient( 100deg, transparent 20%, rgb(255 255 255 / 0.7) 50%, transparent 80% );background-size:220% 100%;animation:rp-card-shimmer 1.6s var(--rp-ease) infinite}@keyframes rp-card-shimmer{from{background-position:180% 0}to{background-position:-80% 0}}.favorite.is-pulsing.sc-rp-recipe-card{animation:rp-favorite-pop 400ms var(--rp-ease)}@keyframes rp-favorite-pop{0%{transform:scale(1)}35%{transform:scale(0.86)}70%{transform:scale(1.16)}100%{transform:scale(1)}}}@media (prefers-reduced-motion: reduce){.card.sc-rp-recipe-card,.media.sc-rp-recipe-card img.sc-rp-recipe-card,.favorite.sc-rp-recipe-card{transition:none}.sc-rp-recipe-card-h:hover .card.sc-rp-recipe-card{transform:none}.sc-rp-recipe-card-h:hover .media.sc-rp-recipe-card img.sc-rp-recipe-card{transform:none}.media.is-loading.sc-rp-recipe-card img.sc-rp-recipe-card{opacity:1}}`;
|
|
149
149
|
|
|
150
150
|
const RecipeCard = class {
|
|
151
151
|
constructor(hostRef) {
|
|
@@ -166,22 +166,59 @@ const RecipeCard = class {
|
|
|
166
166
|
image;
|
|
167
167
|
/** Category label shown under the heading. */
|
|
168
168
|
category;
|
|
169
|
+
/** Cuisine or region, shown as a second meta pill when present. */
|
|
170
|
+
area;
|
|
171
|
+
/** Preparation time in minutes, shown as a meta pill when present. */
|
|
172
|
+
minutes;
|
|
169
173
|
/** Whether this recipe is currently a favorite. Reflected for CSS hooks. */
|
|
170
174
|
favorite = false;
|
|
175
|
+
/**
|
|
176
|
+
* True between the image element being created and its load event.
|
|
177
|
+
*
|
|
178
|
+
* Drives the shimmer placeholder behind the image. Tracked in state rather than with a
|
|
179
|
+
* CSS-only trick because a cached image can complete before this component ever renders,
|
|
180
|
+
* and the load event would then never fire — `onLoad` plus the `complete` check in
|
|
181
|
+
* `onImageRef` covers both orderings.
|
|
182
|
+
*/
|
|
183
|
+
imageLoading = true;
|
|
184
|
+
/** Set when the image URL fails, so a broken link falls back to the gradient. */
|
|
185
|
+
imageFailed = false;
|
|
186
|
+
/** Briefly true after a favorite toggle, driving the press animation. */
|
|
187
|
+
pulsing = false;
|
|
188
|
+
pulseTimer;
|
|
171
189
|
/** Fired when the favorite control is activated. */
|
|
172
190
|
rpFavoriteToggle;
|
|
191
|
+
disconnectedCallback() {
|
|
192
|
+
clearTimeout(this.pulseTimer);
|
|
193
|
+
}
|
|
173
194
|
toggleFavorite = () => {
|
|
195
|
+
this.pulsing = true;
|
|
196
|
+
clearTimeout(this.pulseTimer);
|
|
197
|
+
this.pulseTimer = setTimeout(() => (this.pulsing = false), 400);
|
|
174
198
|
// Emits the intended next state. The consumer owns the data and decides whether
|
|
175
199
|
// the change is applied, so this component never writes to its own prop.
|
|
176
200
|
this.rpFavoriteToggle.emit({ recipeId: this.recipeId, favorite: !this.favorite });
|
|
177
201
|
};
|
|
202
|
+
onImageRef = (element) => {
|
|
203
|
+
// A browser-cached image is already complete by the time the ref runs, and its load
|
|
204
|
+
// event fired before the listener was attached.
|
|
205
|
+
if (element?.complete)
|
|
206
|
+
this.imageLoading = false;
|
|
207
|
+
};
|
|
178
208
|
render() {
|
|
179
|
-
|
|
209
|
+
// Normalized because a consumer that omits the attribute entirely leaves the prop
|
|
210
|
+
// undefined, and `aria-pressed="undefined"` would be dropped from the DOM, leaving a
|
|
211
|
+
// toggle button with no announced state.
|
|
212
|
+
const isFavorite = this.favorite === true;
|
|
213
|
+
const showImage = this.image && !this.imageFailed;
|
|
214
|
+
return (index.h(index.Host, { key: '83f0c244c604277e29c6847a7841e3ddae41b050' }, index.h("article", { key: '7243fc16bee1c4c8ba78feeb658fc8138e9c799d', class: "card" }, index.h("div", { key: '67babe6087e8acaa52379a7749f4ea6001265539', class: { media: true, 'is-loading': showImage && this.imageLoading } }, showImage ? (index.h("img", { src: this.image, alt: "", loading: "lazy", width: "320", height: "240", ref: this.onImageRef, onLoad: () => (this.imageLoading = false), onError: () => (this.imageFailed = true) })) : (index.h("div", { class: "media-fallback", "aria-hidden": "true" })), index.h("div", { key: '7f3dd8af818e08c1c8528b2cb474caf7f045651d', class: "scrim", "aria-hidden": "true" }), index.h("div", { key: 'f3e6442a93cefdcbbe20a2e44026370ca6e5f9a6', class: "badges" }, index.h("slot", { key: '18351d8d6f05b507d754fe2760118f51d6ab7a2b' })), index.h("button", { key: 'c574fc6e66243f30c75f0ff618e27025a2c9dfd6', type: "button", class: { favorite: true, 'is-pulsing': this.pulsing }, onClick: this.toggleFavorite, "aria-pressed": isFavorite ? 'true' : 'false', "aria-label": isFavorite
|
|
215
|
+
? `Remove ${this.recipeTitle} from favorites`
|
|
216
|
+
: `Add ${this.recipeTitle} to favorites` }, index.h("svg", { key: '54ed86ab35d9afb25b21fe50c036ef7cb3a8d92a', viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true" }, index.h("path", { key: '4550aaf0e5cc38fc650014ae6c9cc5f7b0c4ec40', d: "M12 21s-7.5-4.7-9.3-9A5.2 5.2 0 0 1 12 6.5 5.2 5.2 0 0 1 21.3 12c-1.8 4.3-9.3 9-9.3 9z" })))), index.h("div", { key: '20710609101f93f2e3fda399e3c8fc6cab59531b', class: "body" }, index.h("h3", { key: 'dbd67d2f6b1645a90f3b5071dedf7196c57f14b0', class: "title" }, this.recipeTitle), index.h("div", { key: 'a48a0b6c1d60fa24bcb191857d8f04d76906bc78', class: "meta" }, this.category && index.h("span", { key: '6a4c805c85ac8fddb8e316ceca3d99148df78f47', class: "pill pill-category" }, this.category), this.area && index.h("span", { key: '0e69805236fff32521dbd983889f07f6b138b629', class: "pill" }, this.area), this.minutes ? index.h("span", { class: "pill" }, this.minutes, " min") : null)), index.h("div", { key: '362d3f73ec32326cc50e3fdec7977237b9cfd1c8', class: "actions" }, index.h("slot", { key: '6822a6ad44f0414afc97c6b802f0cec276e217d7', name: "actions" })))));
|
|
180
217
|
}
|
|
181
218
|
};
|
|
182
219
|
RecipeCard.style = rpRecipeCardCss();
|
|
183
220
|
|
|
184
|
-
const rpSearchBarCss = () => `.sc-rp-search-bar-h{display:block;font-family:var(--rp-font-sans)}.bar.sc-rp-search-bar{display:flex;gap:var(--rp-space-2);align-items:center
|
|
221
|
+
const rpSearchBarCss = () => `.sc-rp-search-bar-h{display:block;font-family:var(--rp-font-sans)}.bar.sc-rp-search-bar{display:flex;gap:var(--rp-space-2);align-items:center;padding:5px 5px 5px var(--rp-space-4);background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-pill);box-shadow:var(--rp-shadow-sm);transition:border-color var(--rp-duration) var(--rp-ease), box-shadow var(--rp-duration) var(--rp-ease)}.bar.sc-rp-search-bar:hover{border-color:var(--rp-color-border-strong)}.bar.sc-rp-search-bar:focus-within{border-color:var(--rp-color-focus);box-shadow:var(--rp-shadow-sm), var(--rp-focus-halo)}.icon.sc-rp-search-bar{flex-shrink:0;fill:none;stroke:var(--rp-color-text-subtle);stroke-width:2;stroke-linecap:round;transition:stroke var(--rp-duration) var(--rp-ease)}.bar.sc-rp-search-bar:focus-within .icon.sc-rp-search-bar{stroke:var(--rp-color-focus)}.field.sc-rp-search-bar{flex:1;min-width:0;padding:var(--rp-space-2) 0;font:inherit;font-size:var(--rp-font-size-md);color:var(--rp-color-text);background:none;border:none}.field.sc-rp-search-bar::placeholder{color:var(--rp-color-text-subtle)}.field.sc-rp-search-bar:focus{outline:none}.field.sc-rp-search-bar::-webkit-search-cancel-button{display:none}.clear.sc-rp-search-bar{display:grid;place-items:center;width:30px;height:30px;padding:0;color:var(--rp-color-text-subtle);cursor:pointer;background:none;border:none;border-radius:50%;transition:color var(--rp-duration-fast) var(--rp-ease), background-color var(--rp-duration-fast) var(--rp-ease)}.clear.sc-rp-search-bar svg.sc-rp-search-bar{fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}.clear.sc-rp-search-bar:hover{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.submit.sc-rp-search-bar{flex-shrink:0;padding:var(--rp-space-2) var(--rp-space-5);font:inherit;font-size:var(--rp-font-size-md);font-weight:600;color:var(--rp-color-accent-contrast);cursor:pointer;background:var(--rp-color-accent);border:none;border-radius:var(--rp-radius-pill);transition:background-color var(--rp-duration-fast) var(--rp-ease), transform var(--rp-duration-fast) var(--rp-ease)}.submit.sc-rp-search-bar:hover{background:var(--rp-color-accent-hover)}.submit.sc-rp-search-bar:active{transform:scale(0.97)}.field.sc-rp-search-bar:focus-visible,.submit.sc-rp-search-bar:focus-visible,.clear.sc-rp-search-bar:focus-visible{outline:var(--rp-focus-ring);outline-offset:var(--rp-focus-offset)}@media (max-width: 480px){.submit.sc-rp-search-bar{padding-inline:var(--rp-space-4)}}@media (prefers-reduced-motion: reduce){.bar.sc-rp-search-bar,.icon.sc-rp-search-bar,.clear.sc-rp-search-bar,.submit.sc-rp-search-bar{transition:none}.submit.sc-rp-search-bar:active{transform:none}}`;
|
|
185
222
|
|
|
186
223
|
const SearchBar = class {
|
|
187
224
|
constructor(hostRef) {
|
|
@@ -223,7 +260,7 @@ const SearchBar = class {
|
|
|
223
260
|
this.rpClear.emit();
|
|
224
261
|
};
|
|
225
262
|
render() {
|
|
226
|
-
return (index.h(index.Host, { key: '
|
|
263
|
+
return (index.h(index.Host, { key: '8b9328563d52d5cc0ae412bb5c3d513385705467' }, index.h("form", { key: 'a05c8de20f34fb4411ce22d04685842e38bebb93', class: "bar", role: "search", onSubmit: this.onSubmit }, index.h("svg", { key: '486ce7975b594f929c254b4bcbaf366ff35da2a5', class: "icon", viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true" }, index.h("circle", { key: 'a3f1a9aa7e6b3309ef69273210a19b831ccfcfee', cx: "11", cy: "11", r: "7" }), index.h("path", { key: 'a4ebc02325f3ff0f24dfaca637a54e305be260ba', d: "m20 20-3.6-3.6" })), index.h("input", { key: '62361e4ae2ceaf13156d9feb6e3e8f5021badb86', type: "search", class: "field", value: this.draft, placeholder: this.placeholder, "aria-label": this.label, onInput: this.onInput }), this.draft && (index.h("button", { key: '81f67cb9edbdf6f5040fdabbb1d355b38d51ff9e', type: "button", class: "clear", onClick: this.onClear, "aria-label": "Clear search" }, index.h("svg", { key: 'de3195194e0a32075ba1f2e1e506d3409fd177fb', viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, index.h("path", { key: '03510f9ce6e1e2d7a27b03f72674819437f6d903', d: "M6 6l12 12M18 6L6 18" })))), index.h("button", { key: '17430f0dc661d72613a7a177488eab949ff561a0', type: "submit", class: "submit" }, "Search"))));
|
|
227
264
|
}
|
|
228
265
|
static get watchers() { return {
|
|
229
266
|
"value": [{
|