recipe-planner-ui 1.6.0 → 1.6.1

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.
@@ -68,19 +68,59 @@ const Modal = class {
68
68
  /** Fired when the user dismisses the dialog via Escape, the backdrop, or the close button. */
69
69
  rpClose;
70
70
  previouslyFocused = null;
71
+ /** Page offset captured while the background is locked, restored when it is released. */
72
+ lockedScrollY = 0;
71
73
  onOpenChange(isOpen) {
72
74
  if (isOpen) {
73
75
  this.previouslyFocused = document.activeElement;
74
76
  document.addEventListener('keydown', this.onKeydown);
77
+ this.lockBackground();
75
78
  // The dialog content renders in the same tick, so defer focus until it exists.
76
79
  requestAnimationFrame(() => this.focusFirstField());
77
80
  }
78
81
  else {
79
82
  document.removeEventListener('keydown', this.onKeydown);
83
+ this.unlockBackground();
80
84
  this.previouslyFocused?.focus();
81
85
  this.previouslyFocused = null;
82
86
  }
83
87
  }
88
+ /**
89
+ * Freezes the page behind the dialog.
90
+ *
91
+ * Without this the page is still scrollable underneath, and on a phone that is what a
92
+ * touch drag inside the dialog ends up moving: dragging a long option list scrolled the
93
+ * page behind it rather than the list, so the options below the fold were unreachable.
94
+ * `overscroll-behavior` on the list is not enough on its own — it stops a scroll
95
+ * *chaining* outward once the list ends, but not the page claiming the gesture.
96
+ *
97
+ * `position: fixed` rather than `overflow: hidden`, because iOS Safari ignores the
98
+ * latter on `body`. Fixing the body collapses it to the top of the document, so the
99
+ * offset is captured and re-applied as a negative inset, then restored on release —
100
+ * otherwise closing the dialog would jump the page back to the top.
101
+ */
102
+ lockBackground() {
103
+ if (document.body.dataset.rpModalLock)
104
+ return; // A nested dialog must not re-lock.
105
+ this.lockedScrollY = window.scrollY;
106
+ document.body.dataset.rpModalLock = 'true';
107
+ document.body.style.position = 'fixed';
108
+ document.body.style.top = `-${this.lockedScrollY}px`;
109
+ document.body.style.insetInline = '0';
110
+ // The scrollbar disappears with the fixed body; reserving its width stops the page
111
+ // shifting sideways as the dialog opens.
112
+ document.body.style.overflowY = 'scroll';
113
+ }
114
+ unlockBackground() {
115
+ if (!document.body.dataset.rpModalLock)
116
+ return;
117
+ delete document.body.dataset.rpModalLock;
118
+ document.body.style.removeProperty('position');
119
+ document.body.style.removeProperty('top');
120
+ document.body.style.removeProperty('inset-inline');
121
+ document.body.style.removeProperty('overflow-y');
122
+ window.scrollTo(0, this.lockedScrollY);
123
+ }
84
124
  componentDidLoad() {
85
125
  // A dialog can be mounted already open, in which case @Watch never fires.
86
126
  if (this.open)
@@ -89,6 +129,9 @@ const Modal = class {
89
129
  disconnectedCallback() {
90
130
  // Without this, every mount of a page containing a modal leaks a document listener.
91
131
  document.removeEventListener('keydown', this.onKeydown);
132
+ // A dialog unmounted while open would otherwise leave the page frozen with no way
133
+ // back — navigating away with one on screen is the ordinary way that happens.
134
+ this.unlockBackground();
92
135
  }
93
136
  /**
94
137
  * Moves focus to the first focusable control inside the dialog.
@@ -287,8 +330,15 @@ const SearchBar = class {
287
330
  };
288
331
  SearchBar.style = rpSearchBarCss();
289
332
 
290
- const rpSelectCss = () => `.sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;overscroll-behavior:contain;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}`;
333
+ const rpSelectCss = () => `.sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;touch-action:pan-y;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}`;
291
334
 
335
+ /**
336
+ * Movement in CSS pixels that separates a tap on an option from a scroll of the list.
337
+ *
338
+ * Below it the finger was choosing; above it, it was dragging the list and must not select
339
+ * whatever it happens to be over when it lifts.
340
+ */
341
+ const DRAG_SLOP = 10;
292
342
  const Select = class {
293
343
  constructor(hostRef) {
294
344
  index.registerInstance(this, hostRef);
@@ -327,6 +377,14 @@ const Select = class {
327
377
  rpSelectChange;
328
378
  triggerEl;
329
379
  listEl;
380
+ /**
381
+ * The option a finger is currently resting on, and where it landed.
382
+ *
383
+ * Held between `pointerdown` and `pointerup` so the release can tell a tap from a scroll
384
+ * by how far the finger travelled. Not `@State` — it drives no rendering, and making it
385
+ * reactive would re-render the list on every press.
386
+ */
387
+ pressedOption = null;
330
388
  /** Buffer for type-ahead, cleared after a pause, matching native select behaviour. */
331
389
  typeBuffer = '';
332
390
  typeTimer;
@@ -604,7 +662,7 @@ const Select = class {
604
662
  const selected = this.selectedOption;
605
663
  const listId = 'rp-select-list';
606
664
  const activeId = this.activeIndex >= 0 ? `rp-select-option-${this.activeIndex}` : undefined;
607
- return (index.h(index.Host, { key: 'ebc4162f0e81b6d0ff79fd9a0967030ffa01c483' }, index.h("div", { key: '99ff2315652ccec4f747280754367818ad5a7bae', class: "wrap" }, index.h("button", { key: '3464c691b00cb4e0b4ffed094209d103cd4ccd36', type: "button", class: "trigger", ref: (element) => (this.triggerEl = element), disabled: this.disabled, role: "combobox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": listId, "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-activedescendant": this.open ? activeId : undefined, onKeyDown: this.onKeyDown,
665
+ return (index.h(index.Host, { key: 'ff24ed1943638d0a255238846b55f6a2e0042824' }, index.h("div", { key: 'e2750500d5d349f64e66e9d9a28d3f5c37ba4e78', class: "wrap" }, index.h("button", { key: '3ff9611c6f105d1fdc26ca9c332bf2f18efc8983', type: "button", class: "trigger", ref: (element) => (this.triggerEl = element), disabled: this.disabled, role: "combobox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": listId, "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-activedescendant": this.open ? activeId : undefined, onKeyDown: this.onKeyDown,
608
666
  /*
609
667
  Toggled on pointerdown rather than click so one press produces one state
610
668
  change — the document listener that dismisses an open control runs on the
@@ -616,20 +674,47 @@ const Select = class {
616
674
  event.preventDefault();
617
675
  this.triggerEl?.focus();
618
676
  this.open = !this.open;
619
- } }, index.h("span", { key: '169714fb00d19f3ab58822d113fb994424995e90', class: { 'trigger-value': true, 'is-placeholder': !selected } }, selected?.label ?? this.placeholder), index.h("svg", { key: '002c4c2783d9f1bc2a3802404e7d16025478f65d', class: "chevron", viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, index.h("path", { key: 'b5970c61cc218dda77e7cbfebee34e533e76bae2', d: "m6 9 6 6 6-6" }))), this.open && (index.h("div", { key: '26a3d38fcb704ee018e90fae2601539e04a8fa07', class: "list", id: listId, role: "listbox", tabindex: -1, "aria-label": this.label || undefined, ref: (element) => (this.listEl = element) }, options.length === 0 ? (index.h("p", { class: "empty" }, "No options")) : (options.map((option, index$1) => (index.h("button", { key: option.value, id: `rp-select-option-${index$1}`, type: "button", role: "option", "aria-selected": option.value === this.value ? 'true' : 'false', class: {
677
+ } }, index.h("span", { key: '26f8595bad37815f436366c4c3d3fc5a923d7aa5', class: { 'trigger-value': true, 'is-placeholder': !selected } }, selected?.label ?? this.placeholder), index.h("svg", { key: '782c3417d87d24cfabcc0548d2caf4b604006720', class: "chevron", viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, index.h("path", { key: 'f11b0cf117312f97a8e94dbd664f769a542515d9', d: "m6 9 6 6 6-6" }))), this.open && (index.h("div", { key: '76bca46ff9374b459da8a53881c4672b9db7f4a0', class: "list", id: listId, role: "listbox", tabindex: -1, "aria-label": this.label || undefined, ref: (element) => (this.listEl = element) }, options.length === 0 ? (index.h("p", { class: "empty" }, "No options")) : (options.map((option, index$1) => (index.h("button", { key: option.value, id: `rp-select-option-${index$1}`, type: "button", role: "option", "aria-selected": option.value === this.value ? 'true' : 'false', class: {
620
678
  option: true,
621
679
  'is-selected': option.value === this.value,
622
680
  'is-active': index$1 === this.activeIndex,
623
681
  }, onPointerDown: (event) => {
624
- // Keeps focus on the trigger; the press is the selection.
682
+ /**
683
+ * A mouse commits on the press, because a press with a mouse is
684
+ * unambiguous and `preventDefault` here is what keeps focus on the
685
+ * trigger rather than moving it to the option.
686
+ *
687
+ * A touch cannot commit yet: the same press is also how the list is
688
+ * scrolled, and committing on contact selected whichever option the
689
+ * finger happened to land on the moment a scroll began. Touch is
690
+ * resolved on release instead, by the handlers below.
691
+ */
692
+ if (event.pointerType !== 'mouse') {
693
+ this.pressedOption = {
694
+ value: option.value,
695
+ x: event.clientX,
696
+ y: event.clientY,
697
+ };
698
+ return;
699
+ }
625
700
  event.preventDefault();
626
- this.choose(option,
627
- // Where to expect the touch's synthetic click, so it can be
628
- // absorbed before it reaches whatever the list was covering.
629
- event.pointerType === 'mouse'
630
- ? undefined
631
- : { x: event.clientX, y: event.clientY });
632
- }, onMouseEnter: () => (this.activeIndex = index$1) }, index.h("span", { class: "option-text" }, option.label), option.value === this.value && (index.h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, index.h("path", { d: "m5 13 4 4L19 7" }))))))))))));
701
+ this.choose(option);
702
+ }, onPointerUp: (event) => {
703
+ if (event.pointerType === 'mouse')
704
+ return;
705
+ const pressed = this.pressedOption;
706
+ this.pressedOption = null;
707
+ if (!pressed || pressed.value !== option.value)
708
+ return;
709
+ /**
710
+ * Only a finger that stayed put was choosing; one that travelled was
711
+ * scrolling the list, and must not select whatever it ends up over.
712
+ */
713
+ const moved = Math.hypot(event.clientX - pressed.x, event.clientY - pressed.y);
714
+ if (moved > DRAG_SLOP)
715
+ return;
716
+ this.choose(option, { x: event.clientX, y: event.clientY });
717
+ }, onPointerCancel: () => (this.pressedOption = null), onMouseEnter: () => (this.activeIndex = index$1) }, index.h("span", { class: "option-text" }, option.label), option.value === this.value && (index.h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, index.h("path", { d: "m5 13 4 4L19 7" }))))))))))));
633
718
  }
634
719
  static get watchers() { return {
635
720
  "open": [{
@@ -18,19 +18,59 @@ export class Modal {
18
18
  /** Fired when the user dismisses the dialog via Escape, the backdrop, or the close button. */
19
19
  rpClose;
20
20
  previouslyFocused = null;
21
+ /** Page offset captured while the background is locked, restored when it is released. */
22
+ lockedScrollY = 0;
21
23
  onOpenChange(isOpen) {
22
24
  if (isOpen) {
23
25
  this.previouslyFocused = document.activeElement;
24
26
  document.addEventListener('keydown', this.onKeydown);
27
+ this.lockBackground();
25
28
  // The dialog content renders in the same tick, so defer focus until it exists.
26
29
  requestAnimationFrame(() => this.focusFirstField());
27
30
  }
28
31
  else {
29
32
  document.removeEventListener('keydown', this.onKeydown);
33
+ this.unlockBackground();
30
34
  this.previouslyFocused?.focus();
31
35
  this.previouslyFocused = null;
32
36
  }
33
37
  }
38
+ /**
39
+ * Freezes the page behind the dialog.
40
+ *
41
+ * Without this the page is still scrollable underneath, and on a phone that is what a
42
+ * touch drag inside the dialog ends up moving: dragging a long option list scrolled the
43
+ * page behind it rather than the list, so the options below the fold were unreachable.
44
+ * `overscroll-behavior` on the list is not enough on its own — it stops a scroll
45
+ * *chaining* outward once the list ends, but not the page claiming the gesture.
46
+ *
47
+ * `position: fixed` rather than `overflow: hidden`, because iOS Safari ignores the
48
+ * latter on `body`. Fixing the body collapses it to the top of the document, so the
49
+ * offset is captured and re-applied as a negative inset, then restored on release —
50
+ * otherwise closing the dialog would jump the page back to the top.
51
+ */
52
+ lockBackground() {
53
+ if (document.body.dataset.rpModalLock)
54
+ return; // A nested dialog must not re-lock.
55
+ this.lockedScrollY = window.scrollY;
56
+ document.body.dataset.rpModalLock = 'true';
57
+ document.body.style.position = 'fixed';
58
+ document.body.style.top = `-${this.lockedScrollY}px`;
59
+ document.body.style.insetInline = '0';
60
+ // The scrollbar disappears with the fixed body; reserving its width stops the page
61
+ // shifting sideways as the dialog opens.
62
+ document.body.style.overflowY = 'scroll';
63
+ }
64
+ unlockBackground() {
65
+ if (!document.body.dataset.rpModalLock)
66
+ return;
67
+ delete document.body.dataset.rpModalLock;
68
+ document.body.style.removeProperty('position');
69
+ document.body.style.removeProperty('top');
70
+ document.body.style.removeProperty('inset-inline');
71
+ document.body.style.removeProperty('overflow-y');
72
+ window.scrollTo(0, this.lockedScrollY);
73
+ }
34
74
  componentDidLoad() {
35
75
  // A dialog can be mounted already open, in which case @Watch never fires.
36
76
  if (this.open)
@@ -39,6 +79,9 @@ export class Modal {
39
79
  disconnectedCallback() {
40
80
  // Without this, every mount of a page containing a modal leaks a document listener.
41
81
  document.removeEventListener('keydown', this.onKeydown);
82
+ // A dialog unmounted while open would otherwise leave the page frozen with no way
83
+ // back — navigating away with one on screen is the ordinary way that happens.
84
+ this.unlockBackground();
42
85
  }
43
86
  /**
44
87
  * Moves focus to the first focusable control inside the dialog.
@@ -87,7 +87,12 @@
87
87
  max-height: min(260px, var(--rp-select-max-height, 260px));
88
88
  padding: var(--rp-space-1);
89
89
  overflow-y: auto;
90
+ /* Claims the vertical gesture for the list, so a finger dragging over a long list
91
+ scrolls the options rather than whatever lies behind the dialog. */
92
+ touch-action: pan-y;
93
+ /* Stops a scroll that reaches either end from chaining outward and moving the page. */
90
94
  overscroll-behavior: contain;
95
+ -webkit-overflow-scrolling: touch;
91
96
  background: var(--rp-color-surface);
92
97
  border: 1px solid var(--rp-color-border);
93
98
  border-radius: var(--rp-radius-lg);
@@ -1,4 +1,11 @@
1
1
  import { Host, h } from "@stencil/core";
2
+ /**
3
+ * Movement in CSS pixels that separates a tap on an option from a scroll of the list.
4
+ *
5
+ * Below it the finger was choosing; above it, it was dragging the list and must not select
6
+ * whatever it happens to be over when it lifts.
7
+ */
8
+ const DRAG_SLOP = 10;
2
9
  /**
3
10
  * A single-select control with a styled option list.
4
11
  *
@@ -48,6 +55,14 @@ export class Select {
48
55
  rpSelectChange;
49
56
  triggerEl;
50
57
  listEl;
58
+ /**
59
+ * The option a finger is currently resting on, and where it landed.
60
+ *
61
+ * Held between `pointerdown` and `pointerup` so the release can tell a tap from a scroll
62
+ * by how far the finger travelled. Not `@State` — it drives no rendering, and making it
63
+ * reactive would re-render the list on every press.
64
+ */
65
+ pressedOption = null;
51
66
  /** Buffer for type-ahead, cleared after a pause, matching native select behaviour. */
52
67
  typeBuffer = '';
53
68
  typeTimer;
@@ -325,7 +340,7 @@ export class Select {
325
340
  const selected = this.selectedOption;
326
341
  const listId = 'rp-select-list';
327
342
  const activeId = this.activeIndex >= 0 ? `rp-select-option-${this.activeIndex}` : undefined;
328
- return (h(Host, { key: 'ebc4162f0e81b6d0ff79fd9a0967030ffa01c483' }, h("div", { key: '99ff2315652ccec4f747280754367818ad5a7bae', class: "wrap" }, h("button", { key: '3464c691b00cb4e0b4ffed094209d103cd4ccd36', type: "button", class: "trigger", ref: (element) => (this.triggerEl = element), disabled: this.disabled, role: "combobox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": listId, "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-activedescendant": this.open ? activeId : undefined, onKeyDown: this.onKeyDown,
343
+ return (h(Host, { key: 'ff24ed1943638d0a255238846b55f6a2e0042824' }, h("div", { key: 'e2750500d5d349f64e66e9d9a28d3f5c37ba4e78', class: "wrap" }, h("button", { key: '3ff9611c6f105d1fdc26ca9c332bf2f18efc8983', type: "button", class: "trigger", ref: (element) => (this.triggerEl = element), disabled: this.disabled, role: "combobox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": listId, "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-activedescendant": this.open ? activeId : undefined, onKeyDown: this.onKeyDown,
329
344
  /*
330
345
  Toggled on pointerdown rather than click so one press produces one state
331
346
  change — the document listener that dismisses an open control runs on the
@@ -337,20 +352,47 @@ export class Select {
337
352
  event.preventDefault();
338
353
  this.triggerEl?.focus();
339
354
  this.open = !this.open;
340
- } }, h("span", { key: '169714fb00d19f3ab58822d113fb994424995e90', class: { 'trigger-value': true, 'is-placeholder': !selected } }, selected?.label ?? this.placeholder), h("svg", { key: '002c4c2783d9f1bc2a3802404e7d16025478f65d', class: "chevron", viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, h("path", { key: 'b5970c61cc218dda77e7cbfebee34e533e76bae2', d: "m6 9 6 6 6-6" }))), this.open && (h("div", { key: '26a3d38fcb704ee018e90fae2601539e04a8fa07', class: "list", id: listId, role: "listbox", tabindex: -1, "aria-label": this.label || undefined, ref: (element) => (this.listEl = element) }, options.length === 0 ? (h("p", { class: "empty" }, "No options")) : (options.map((option, index) => (h("button", { key: option.value, id: `rp-select-option-${index}`, type: "button", role: "option", "aria-selected": option.value === this.value ? 'true' : 'false', class: {
355
+ } }, h("span", { key: '26f8595bad37815f436366c4c3d3fc5a923d7aa5', class: { 'trigger-value': true, 'is-placeholder': !selected } }, selected?.label ?? this.placeholder), h("svg", { key: '782c3417d87d24cfabcc0548d2caf4b604006720', class: "chevron", viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, h("path", { key: 'f11b0cf117312f97a8e94dbd664f769a542515d9', d: "m6 9 6 6 6-6" }))), this.open && (h("div", { key: '76bca46ff9374b459da8a53881c4672b9db7f4a0', class: "list", id: listId, role: "listbox", tabindex: -1, "aria-label": this.label || undefined, ref: (element) => (this.listEl = element) }, options.length === 0 ? (h("p", { class: "empty" }, "No options")) : (options.map((option, index) => (h("button", { key: option.value, id: `rp-select-option-${index}`, type: "button", role: "option", "aria-selected": option.value === this.value ? 'true' : 'false', class: {
341
356
  option: true,
342
357
  'is-selected': option.value === this.value,
343
358
  'is-active': index === this.activeIndex,
344
359
  }, onPointerDown: (event) => {
345
- // Keeps focus on the trigger; the press is the selection.
360
+ /**
361
+ * A mouse commits on the press, because a press with a mouse is
362
+ * unambiguous and `preventDefault` here is what keeps focus on the
363
+ * trigger rather than moving it to the option.
364
+ *
365
+ * A touch cannot commit yet: the same press is also how the list is
366
+ * scrolled, and committing on contact selected whichever option the
367
+ * finger happened to land on the moment a scroll began. Touch is
368
+ * resolved on release instead, by the handlers below.
369
+ */
370
+ if (event.pointerType !== 'mouse') {
371
+ this.pressedOption = {
372
+ value: option.value,
373
+ x: event.clientX,
374
+ y: event.clientY,
375
+ };
376
+ return;
377
+ }
346
378
  event.preventDefault();
347
- this.choose(option,
348
- // Where to expect the touch's synthetic click, so it can be
349
- // absorbed before it reaches whatever the list was covering.
350
- event.pointerType === 'mouse'
351
- ? undefined
352
- : { x: event.clientX, y: event.clientY });
353
- }, onMouseEnter: () => (this.activeIndex = index) }, h("span", { class: "option-text" }, option.label), option.value === this.value && (h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, h("path", { d: "m5 13 4 4L19 7" }))))))))))));
379
+ this.choose(option);
380
+ }, onPointerUp: (event) => {
381
+ if (event.pointerType === 'mouse')
382
+ return;
383
+ const pressed = this.pressedOption;
384
+ this.pressedOption = null;
385
+ if (!pressed || pressed.value !== option.value)
386
+ return;
387
+ /**
388
+ * Only a finger that stayed put was choosing; one that travelled was
389
+ * scrolling the list, and must not select whatever it ends up over.
390
+ */
391
+ const moved = Math.hypot(event.clientX - pressed.x, event.clientY - pressed.y);
392
+ if (moved > DRAG_SLOP)
393
+ return;
394
+ this.choose(option, { x: event.clientX, y: event.clientY });
395
+ }, onPointerCancel: () => (this.pressedOption = null), onMouseEnter: () => (this.activeIndex = index) }, h("span", { class: "option-text" }, option.label), option.value === this.value && (h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, h("path", { d: "m5 13 4 4L19 7" }))))))))))));
354
396
  }
355
397
  static get is() { return "rp-select"; }
356
398
  static get encapsulation() { return "scoped"; }
@@ -0,0 +1 @@
1
+ import{p as t,H as e,c as r,h as s,a as o,t as i}from"./index.js";const a=t(class extends e{constructor(t){super(),!1!==t&&this.__registerHost(),this.rpSelectChange=r(this,"rpSelectChange")}get el(){return this}options=[];value="";label="";placeholder="Choose…";open=!1;disabled=!1;compact=!1;dropUp=!1;activeIndex=-1;rpSelectChange;triggerEl;listEl;pressedOption=null;typeBuffer="";typeTimer;onOpenChange(t){if(!t)return window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0),this.el.style.removeProperty("--rp-select-max-height"),void(this.dropUp=!1);this.activeIndex=Math.max(0,this.normalizedOptions.findIndex((t=>t.value===this.value))),requestAnimationFrame((()=>requestAnimationFrame((()=>{this.position(),this.scrollActiveIntoView()})))),window.addEventListener("resize",this.position),window.addEventListener("scroll",this.onAncestorScroll,!0)}onOptionsChange(){this.open&&requestAnimationFrame((()=>requestAnimationFrame((()=>this.position()))))}disconnectedCallback(){clearTimeout(this.typeTimer),window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0)}onAncestorScroll=t=>{t.target!==this.listEl&&this.position()};position=()=>{if(!this.open||!this.triggerEl)return;const t=this.triggerEl.getBoundingClientRect(),e=this.clippingBounds(),r=Math.min(window.innerHeight,e.bottom),s=Math.max(0,e.top),o=r-t.bottom-8-12,i=t.top-s-8-12,a=o<(this.listEl?Math.min(260,this.listEl.scrollHeight):Math.min(260,40*this.normalizedOptions.length+8))&&i>o;this.dropUp=a;const n=Math.max(96,Math.floor(a?i:o));this.el.style.setProperty("--rp-select-max-height",`${n}px`)};clippingBounds(){let t=this.el.parentElement;for(;t&&t!==document.body;){const e=getComputedStyle(t);if("visible"!==e.overflow&&"visible"!==e.overflowY){const e=t.getBoundingClientRect();if(e.height>0)return{top:e.top,bottom:e.bottom}}t=t.parentElement}return{top:0,bottom:window.innerHeight}}async focusControl(){this.triggerEl?.focus()}onDocumentPointerDown(t){this.open&&(this.el.contains(t.target)||(this.open=!1))}get normalizedOptions(){return Array.isArray(this.options)?this.options:[]}get selectedOption(){return this.normalizedOptions.find((t=>t.value===this.value))}choose(t,e){this.value=t.value,this.open=!1,this.rpSelectChange.emit(t.value),this.triggerEl?.focus(),e&&this.swallowGhostClick(e.x,e.y)}swallowGhostClick(t,e){const r=r=>{Math.hypot(r.clientX-t,r.clientY-e)>24||(r.preventDefault(),r.stopPropagation(),s())},s=()=>{window.clearTimeout(o),document.removeEventListener("click",r,!0)};document.addEventListener("click",r,!0);const o=window.setTimeout(s,500)}scrollActiveIntoView(){const t=this.listEl?.querySelector(".option.is-active");t?.scrollIntoView({block:"nearest"})}move(t){const e=this.normalizedOptions;if(0===e.length)return;const r=this.activeIndex+t;this.activeIndex=r<0?e.length-1:r%e.length,requestAnimationFrame((()=>this.scrollActiveIntoView()))}typeAhead(t){clearTimeout(this.typeTimer),this.typeBuffer+=t.toLowerCase(),this.typeTimer=setTimeout((()=>this.typeBuffer=""),600);const e=this.normalizedOptions.findIndex((t=>t.label.toLowerCase().startsWith(this.typeBuffer)));-1!==e&&(this.open?(this.activeIndex=e,requestAnimationFrame((()=>this.scrollActiveIntoView()))):this.choose(this.normalizedOptions[e]))}onKeyDown=t=>{if(!this.disabled)switch(t.key){case"ArrowDown":return t.preventDefault(),void(this.open?this.move(1):this.open=!0);case"ArrowUp":return t.preventDefault(),void(this.open?this.move(-1):this.open=!0);case"Home":if(!this.open)return;return t.preventDefault(),this.activeIndex=0,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"End":if(!this.open)return;return t.preventDefault(),this.activeIndex=this.normalizedOptions.length-1,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"Enter":case" ":return t.preventDefault(),void(this.open?this.activeIndex>=0&&this.choose(this.normalizedOptions[this.activeIndex]):this.open=!0);case"Escape":if(!this.open)return;return t.preventDefault(),void(this.open=!1);case"Tab":return void(this.open=!1);default:1!==t.key.length||t.metaKey||t.ctrlKey||t.altKey||(t.preventDefault(),this.typeAhead(t.key))}};render(){const t=this.normalizedOptions,e=this.selectedOption,r="rp-select-list";return s(o,{key:"ff24ed1943638d0a255238846b55f6a2e0042824"},s("div",{key:"e2750500d5d349f64e66e9d9a28d3f5c37ba4e78",class:"wrap"},s("button",{key:"3ff9611c6f105d1fdc26ca9c332bf2f18efc8983",type:"button",class:"trigger",ref:t=>this.triggerEl=t,disabled:this.disabled,role:"combobox","aria-expanded":this.open?"true":"false","aria-controls":r,"aria-haspopup":"listbox","aria-label":this.label||void 0,"aria-activedescendant":this.open&&this.activeIndex>=0?`rp-select-option-${this.activeIndex}`:void 0,onKeyDown:this.onKeyDown,onPointerDown:t=>{this.disabled||(t.preventDefault(),this.triggerEl?.focus(),this.open=!this.open)}},s("span",{key:"26f8595bad37815f436366c4c3d3fc5a923d7aa5",class:{"trigger-value":!0,"is-placeholder":!e}},e?.label??this.placeholder),s("svg",{key:"782c3417d87d24cfabcc0548d2caf4b604006720",class:"chevron",viewBox:"0 0 24 24",width:"14",height:"14","aria-hidden":"true"},s("path",{key:"f11b0cf117312f97a8e94dbd664f769a542515d9",d:"m6 9 6 6 6-6"}))),this.open&&s("div",{key:"76bca46ff9374b459da8a53881c4672b9db7f4a0",class:"list",id:r,role:"listbox",tabindex:-1,"aria-label":this.label||void 0,ref:t=>this.listEl=t},0===t.length?s("p",{class:"empty"},"No options"):t.map(((t,e)=>s("button",{key:t.value,id:`rp-select-option-${e}`,type:"button",role:"option","aria-selected":t.value===this.value?"true":"false",class:{option:!0,"is-selected":t.value===this.value,"is-active":e===this.activeIndex},onPointerDown:e=>{"mouse"===e.pointerType?(e.preventDefault(),this.choose(t)):this.pressedOption={value:t.value,x:e.clientX,y:e.clientY}},onPointerUp:e=>{if("mouse"===e.pointerType)return;const r=this.pressedOption;this.pressedOption=null,r&&r.value===t.value&&(Math.hypot(e.clientX-r.x,e.clientY-r.y)>10||this.choose(t,{x:e.clientX,y:e.clientY}))},onPointerCancel:()=>this.pressedOption=null,onMouseEnter:()=>this.activeIndex=e},s("span",{class:"option-text"},t.label),t.value===this.value&&s("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},s("path",{d:"m5 13 4 4L19 7"}))))))))}static get watchers(){return{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}}static get style(){return".sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;touch-action:pan-y;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}"}},[514,"rp-select",{options:[16],value:[1025],label:[1],placeholder:[1],open:[1540],disabled:[516],compact:[516],dropUp:[1540,"drop-up"],activeIndex:[32],focusControl:[64]},[[5,"pointerdown","onDocumentPointerDown"]],{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}]);function n(){"undefined"!=typeof customElements&&["rp-select"].forEach((t=>{"rp-select"===t&&(customElements.get(i(t))||customElements.define(i(t),a))}))}n();export{a as S,n as d}
@@ -1 +1 @@
1
- import{p as t,t as r,H as e,c as s,h as o,a}from"./index.js";import{d as i}from"./p-D4hBkDfU.js";const n=t(class t extends e{constructor(t){super(),!1!==t&&this.__registerHost(),this.rpAddMeal=s(this,"rpAddMeal"),this.rpRemoveMeal=s(this,"rpRemoveMeal"),this.rpMoveMeal=s(this,"rpMoveMeal")}get el(){return this}day;dayLabel="";meals=[];days=[];dayLabels={};normalized=[];dropActive=!1;draggingId=null;pointerKind="unknown";dragDepth=0;pointerDrag=null;ghost=null;hoveredPanel=null;static DRAG_THRESHOLD=8;static HOLD_SLOP=16;static LONG_PRESS_MS=220;static EDGE_ZONE=72;static EDGE_SPEED=14;holdTimer=null;edgeScrollFrame=null;lastPoint={x:0,y:0};rpAddMeal;rpRemoveMeal;rpMoveMeal;componentWillLoad(){this.normalized=Array.isArray(this.meals)?this.meals:[]}componentWillUpdate(){this.normalized=Array.isArray(this.meals)?this.meals:[]}connectedCallback(){document.addEventListener("dragend",this.clearDragState),document.addEventListener("drop",this.clearDragState)}disconnectedCallback(){this.endPointerDrag(),document.removeEventListener("dragend",this.clearDragState),document.removeEventListener("drop",this.clearDragState)}clearDragState=()=>{this.dragDepth=0,this.dropActive=!1,this.draggingId=null};emitMove(t,r,e){e&&e!==r&&this.rpMoveMeal.emit({id:t,from:r,to:e})}onDragStart=(t,r)=>{"touch"!==this.pointerKind?(this.draggingId=r.id,t.dataTransfer?.setData("application/x-rp-meal",JSON.stringify({id:r.id,from:this.day})),t.dataTransfer?.setData("text/plain",r.title),t.dataTransfer&&(t.dataTransfer.effectAllowed="move")):t.preventDefault()};hasMealPayload(t){return t.dataTransfer?.types.includes("application/x-rp-meal")??!1}onDragEnter=t=>{this.hasMealPayload(t)&&(this.dragDepth+=1,this.dropActive=!0)};onDragOver=t=>{this.hasMealPayload(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"))};onDragLeave=t=>{this.hasMealPayload(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&(this.dropActive=!1))};onPointerDown=(r,e)=>{if("mouse"===r.pointerType)return void(this.pointerKind="mouse");this.pointerKind="touch";const s=r.currentTarget;s?.removeAttribute("draggable"),r.target.closest("button, select, label, a, rp-select")||(this.pointerDrag={id:e.id,title:e.title,pointerId:r.pointerId,startX:r.clientX,startY:r.clientY,started:!1},this.lastPoint={x:r.clientX,y:r.clientY},this.holdTimer=window.setTimeout((()=>{this.holdTimer=null,this.pointerDrag&&this.beginPointerDrag()}),t.LONG_PRESS_MS),window.addEventListener("pointermove",this.onPointerMove,{passive:!1}),window.addEventListener("pointerup",this.onPointerUp),window.addEventListener("pointercancel",this.onPointerCancel))};onContextMenuDuringDrag=t=>{this.pointerDrag?.started&&t.preventDefault()};beginPointerDrag(){const t=this.pointerDrag;t&&!t.started&&(t.started=!0,this.draggingId=t.id,this.createGhost(this.cardFor(t.id),t.title),this.moveGhost(this.lastPoint.x,this.lastPoint.y),this.highlightPanelAt(this.lastPoint.x,this.lastPoint.y),this.startEdgeScroll(),document.addEventListener("contextmenu",this.onContextMenuDuringDrag,!0))}onPointerMove=r=>{const e=this.pointerDrag;if(e&&r.pointerId===e.pointerId){if(this.lastPoint={x:Math.min(Math.max(r.clientX,1),window.innerWidth-1),y:Math.min(Math.max(r.clientY,1),window.innerHeight-1)},!e.started){const s=Math.abs(r.clientX-e.startX),o=Math.abs(r.clientY-e.startY),a=Math.hypot(s,o);if(a<t.DRAG_THRESHOLD)return;if(o>s){if(a<t.HOLD_SLOP)return;return void this.scrollFromTouch(r)}this.cancelHold(),this.beginPointerDrag()}r.preventDefault(),this.moveGhost(this.lastPoint.x,this.lastPoint.y),this.highlightPanelAt(this.lastPoint.x,this.lastPoint.y)}};onPointerUp=t=>{const r=this.pointerDrag;if(!r||t.pointerId!==r.pointerId)return;const e=r.started,s=r.id,o=e?this.panelAt(this.lastPoint.x,this.lastPoint.y):null;if(this.endPointerDrag(),!e)return;const a=o?.getAttribute("day");a&&this.emitMove(s,this.day,a)};onPointerCancel=()=>{this.pointerDrag?.started||this.endPointerDrag()};scrollFromTouch(t){const r=this.pointerDrag?.startY??t.clientY;let e=t.clientY;this.endPointerDrag(),window.scrollBy(0,r-t.clientY);const s=r=>{r.pointerId===t.pointerId&&(window.scrollBy(0,e-r.clientY),e=r.clientY,r.preventDefault())},o=()=>{window.removeEventListener("pointermove",s),window.removeEventListener("pointerup",o),window.removeEventListener("pointercancel",o)};window.addEventListener("pointermove",s,{passive:!1}),window.addEventListener("pointerup",o),window.addEventListener("pointercancel",o)}cancelHold(){null!==this.holdTimer&&(clearTimeout(this.holdTimer),this.holdTimer=null)}endPointerDrag(){this.cancelHold(),this.stopEdgeScroll(),document.removeEventListener("contextmenu",this.onContextMenuDuringDrag,!0),this.pointerDrag=null,this.draggingId=null,this.clearHighlight(),this.ghost?.remove(),this.ghost=null,this.el.style.removeProperty("touch-action"),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),window.removeEventListener("pointercancel",this.onPointerCancel)}startEdgeScroll(){if(null!==this.edgeScrollFrame)return;const r=()=>{if(!this.pointerDrag?.started)return void(this.edgeScrollFrame=null);const e=this.lastPoint.y,s=window.innerHeight;let o=0;if(e<t.EDGE_ZONE?o=-t.EDGE_SPEED*(1-e/t.EDGE_ZONE):e>s-t.EDGE_ZONE&&(o=t.EDGE_SPEED*(1-(s-e)/t.EDGE_ZONE)),0!==o){const t=window.scrollY;window.scrollBy(0,o),window.scrollY!==t&&this.highlightPanelAt(this.lastPoint.x,this.lastPoint.y)}this.edgeScrollFrame=requestAnimationFrame(r)};this.edgeScrollFrame=requestAnimationFrame(r)}stopEdgeScroll(){null!==this.edgeScrollFrame&&(cancelAnimationFrame(this.edgeScrollFrame),this.edgeScrollFrame=null)}panelAt(t,r){this.ghost&&(this.ghost.style.display="none");const e=document.elementFromPoint(t,r);this.ghost&&(this.ghost.style.display="");const s=e?.closest("rp-day-slot");return s||this.nearestPanel(t,r)}nearestPanel(t,r){let e=null,s=1/0;for(const o of Array.from(document.querySelectorAll("rp-day-slot"))){const a=o.getBoundingClientRect();if(0===a.width||0===a.height)continue;const i=Math.hypot(Math.max(a.left-t,0,t-a.right),Math.max(a.top-r,0,r-a.bottom));i<s&&(s=i,e=o)}return s<=64?e:null}highlightPanelAt(t,r){const e=this.panelAt(t,r);e!==this.hoveredPanel&&(this.clearHighlight(),e&&e!==this.el&&(e.querySelector(".slot")?.classList.add("is-drop-active"),this.hoveredPanel=e))}clearHighlight(){this.hoveredPanel?.querySelector(".slot")?.classList.remove("is-drop-active"),this.hoveredPanel=null}cardFor(t){const r=this.normalized.findIndex((r=>r.id===t));return r<0?null:this.el.querySelectorAll(".meal")[r]??null}createGhost(t,r){const e=document.createElement("div");if(e.setAttribute("aria-hidden","true"),e.className="rp-drag-ghost",t){const r=t.getBoundingClientRect();e.style.width=r.width+"px";const s=t.cloneNode(!0);s.classList.remove("is-dragging"),s.removeAttribute("draggable");for(const t of Array.from(s.querySelectorAll("rp-select"))){const r=document.createElement("div");r.className=t.className;const e=t.querySelector(".trigger");e&&r.append(e.cloneNode(!0)),t.replaceWith(r)}for(const t of Array.from(s.querySelectorAll("button, input, select, a")))t.style.pointerEvents="none",t.setAttribute("tabindex","-1");e.append(s)}else e.textContent=r;document.body.append(e),this.ghost=e}moveGhost(t,r){if(!this.ghost)return;const e=this.ghost.getBoundingClientRect(),s=window.innerWidth-e.width+12,o=window.innerHeight-e.height+44;this.ghost.style.transform=`translate(${Math.min(Math.max(t,12),Math.max(s,12))}px, ${Math.min(Math.max(r,44),Math.max(o,44))}px)`}onDrop=t=>{const r=t.dataTransfer?.getData("application/x-rp-meal");if(r){t.preventDefault(),this.dragDepth=0,this.dropActive=!1;try{const{id:t,from:e}=JSON.parse(r);this.emitMove(t,e,this.day)}catch{}}};render(){const t=Array.isArray(this.days)?this.days:[],r=this.dayLabels??{},e=this.normalized;return o(a,{key:"05ee7eff0f1ff19f77363539f3f5ccf2d1d96efb"},o("section",{key:"dce7ecf1d85d7d8cd8b988fb6dc06f93810f532a",class:{slot:!0,"is-drop-active":this.dropActive,"is-empty":0===e.length},onDragEnter:this.onDragEnter,onDragOver:this.onDragOver,onDragLeave:this.onDragLeave,onDrop:this.onDrop},o("header",{key:"086dc84dce8943ae814505878fee4dbc1e3acc1a",class:"head"},o("h3",{key:"a37cb66c77bc30ed80e7eb5d9bbe38c2b2c207b6",class:"day"},this.dayLabel||this.day),o("div",{key:"67e62ed1a5754842f8ffd828ac1ce7cd63a5a666",class:"head-right"},e.length>0&&o("span",{key:"c4460980f7998c355e00ea7d0035297b47a8ecb0",class:"count"},e.length),o("button",{key:"5d4a5c5fafa9e63cf6cd323b0e23cd6354a18d3b",type:"button",class:"add",onClick:()=>this.rpAddMeal.emit(this.day),"aria-label":"Add a meal to "+((this.dayLabels??{})[this.day]||this.dayLabel||this.day)},o("svg",{key:"684fc27b7da23ce41a656bc04524b600dec89ee3",viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},o("path",{key:"c22a9bdbccc3a2fee2f59106371afbfd96c9946f",d:"M12 5v14M5 12h14"}))))),0===e.length?o("div",{class:"empty"},o("slot",null,o("svg",{class:"empty-icon",viewBox:"0 0 24 24",width:"26",height:"26","aria-hidden":"true"},o("path",{d:"M4 4h16v16H4z",opacity:"0.35"}),o("path",{d:"M8 2v4M16 2v4M4 10h16"})),o("p",{class:"empty-text"},"No meals planned"))):o("ul",{class:"meals"},e.map((e=>o("li",{class:{meal:!0,"is-dragging":this.draggingId===e.id},key:e.id,draggable:"touch"!==this.pointerKind,onDragStart:t=>this.onDragStart(t,e),onPointerDown:t=>this.onPointerDown(t,e),onContextMenu:t=>{"touch"===this.pointerKind&&t.preventDefault()}},o("span",{class:"grip","aria-hidden":"true"},o("svg",{viewBox:"0 0 24 24",width:"12",height:"12"},o("circle",{cx:"9",cy:"6",r:"1.4"}),o("circle",{cx:"15",cy:"6",r:"1.4"}),o("circle",{cx:"9",cy:"12",r:"1.4"}),o("circle",{cx:"15",cy:"12",r:"1.4"}),o("circle",{cx:"9",cy:"18",r:"1.4"}),o("circle",{cx:"15",cy:"18",r:"1.4"}))),o("span",{class:"meal-title"},e.title),o("div",{class:"meal-actions"},o("rp-select",{class:"move-select",compact:!0,label:`Move ${e.title} to another day`,placeholder:"Move…",options:t.filter((t=>t!==this.day)).map((t=>({value:t,label:r[t]??t}))),onRpSelectChange:t=>this.emitMove(e.id,this.day,t.detail)}),o("button",{type:"button",class:"remove",onClick:()=>this.rpRemoveMeal.emit({id:e.id,day:this.day}),"aria-label":"Remove "+e.title},o("svg",{viewBox:"0 0 24 24",width:"13",height:"13","aria-hidden":"true"},o("path",{d:"M6 6l12 12M18 6L6 18"}))))))))))}static get style(){return".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-1);align-items:center;justify-content:space-between;padding:var(--rp-space-3) var(--rp-space-2) var(--rp-space-3) 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;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;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{min-width:0;position:relative;z-index:1;touch-action:manipulation}.remove.sc-rp-day-slot::before{content:'';position:absolute;inset:-9px}.meal.sc-rp-day-slot:has(rp-select[open]),.meals.sc-rp-day-slot:has(rp-select[open]){overflow:visible}.slot.sc-rp-day-slot:has(rp-select[open]){overflow:visible}.meal.sc-rp-day-slot:has(rp-select[open]){z-index:3}.remove.sc-rp-day-slot{display:grid;place-items:center;touch-action:manipulation;position:relative;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}}"}},[774,"rp-day-slot",{day:[513],dayLabel:[1,"day-label"],meals:[16],days:[16],dayLabels:[16],normalized:[32],dropActive:[32],draggingId:[32],pointerKind:[32]}]);function l(){"undefined"!=typeof customElements&&["rp-day-slot","rp-select"].forEach((t=>{switch(t){case"rp-day-slot":customElements.get(r(t))||customElements.define(r(t),n);break;case"rp-select":customElements.get(r(t))||i()}}))}l();const c=n,d=l;export{c as RpDaySlot,d as defineCustomElement}
1
+ import{p as t,t as r,H as e,c as s,h as o,a}from"./index.js";import{d as i}from"./p-DE3tFqRZ.js";const n=t(class t extends e{constructor(t){super(),!1!==t&&this.__registerHost(),this.rpAddMeal=s(this,"rpAddMeal"),this.rpRemoveMeal=s(this,"rpRemoveMeal"),this.rpMoveMeal=s(this,"rpMoveMeal")}get el(){return this}day;dayLabel="";meals=[];days=[];dayLabels={};normalized=[];dropActive=!1;draggingId=null;pointerKind="unknown";dragDepth=0;pointerDrag=null;ghost=null;hoveredPanel=null;static DRAG_THRESHOLD=8;static HOLD_SLOP=16;static LONG_PRESS_MS=220;static EDGE_ZONE=72;static EDGE_SPEED=14;holdTimer=null;edgeScrollFrame=null;lastPoint={x:0,y:0};rpAddMeal;rpRemoveMeal;rpMoveMeal;componentWillLoad(){this.normalized=Array.isArray(this.meals)?this.meals:[]}componentWillUpdate(){this.normalized=Array.isArray(this.meals)?this.meals:[]}connectedCallback(){document.addEventListener("dragend",this.clearDragState),document.addEventListener("drop",this.clearDragState)}disconnectedCallback(){this.endPointerDrag(),document.removeEventListener("dragend",this.clearDragState),document.removeEventListener("drop",this.clearDragState)}clearDragState=()=>{this.dragDepth=0,this.dropActive=!1,this.draggingId=null};emitMove(t,r,e){e&&e!==r&&this.rpMoveMeal.emit({id:t,from:r,to:e})}onDragStart=(t,r)=>{"touch"!==this.pointerKind?(this.draggingId=r.id,t.dataTransfer?.setData("application/x-rp-meal",JSON.stringify({id:r.id,from:this.day})),t.dataTransfer?.setData("text/plain",r.title),t.dataTransfer&&(t.dataTransfer.effectAllowed="move")):t.preventDefault()};hasMealPayload(t){return t.dataTransfer?.types.includes("application/x-rp-meal")??!1}onDragEnter=t=>{this.hasMealPayload(t)&&(this.dragDepth+=1,this.dropActive=!0)};onDragOver=t=>{this.hasMealPayload(t)&&(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="move"))};onDragLeave=t=>{this.hasMealPayload(t)&&(this.dragDepth=Math.max(0,this.dragDepth-1),0===this.dragDepth&&(this.dropActive=!1))};onPointerDown=(r,e)=>{if("mouse"===r.pointerType)return void(this.pointerKind="mouse");this.pointerKind="touch";const s=r.currentTarget;s?.removeAttribute("draggable"),r.target.closest("button, select, label, a, rp-select")||(this.pointerDrag={id:e.id,title:e.title,pointerId:r.pointerId,startX:r.clientX,startY:r.clientY,started:!1},this.lastPoint={x:r.clientX,y:r.clientY},this.holdTimer=window.setTimeout((()=>{this.holdTimer=null,this.pointerDrag&&this.beginPointerDrag()}),t.LONG_PRESS_MS),window.addEventListener("pointermove",this.onPointerMove,{passive:!1}),window.addEventListener("pointerup",this.onPointerUp),window.addEventListener("pointercancel",this.onPointerCancel))};onContextMenuDuringDrag=t=>{this.pointerDrag?.started&&t.preventDefault()};beginPointerDrag(){const t=this.pointerDrag;t&&!t.started&&(t.started=!0,this.draggingId=t.id,this.createGhost(this.cardFor(t.id),t.title),this.moveGhost(this.lastPoint.x,this.lastPoint.y),this.highlightPanelAt(this.lastPoint.x,this.lastPoint.y),this.startEdgeScroll(),document.addEventListener("contextmenu",this.onContextMenuDuringDrag,!0))}onPointerMove=r=>{const e=this.pointerDrag;if(e&&r.pointerId===e.pointerId){if(this.lastPoint={x:Math.min(Math.max(r.clientX,1),window.innerWidth-1),y:Math.min(Math.max(r.clientY,1),window.innerHeight-1)},!e.started){const s=Math.abs(r.clientX-e.startX),o=Math.abs(r.clientY-e.startY),a=Math.hypot(s,o);if(a<t.DRAG_THRESHOLD)return;if(o>s){if(a<t.HOLD_SLOP)return;return void this.scrollFromTouch(r)}this.cancelHold(),this.beginPointerDrag()}r.preventDefault(),this.moveGhost(this.lastPoint.x,this.lastPoint.y),this.highlightPanelAt(this.lastPoint.x,this.lastPoint.y)}};onPointerUp=t=>{const r=this.pointerDrag;if(!r||t.pointerId!==r.pointerId)return;const e=r.started,s=r.id,o=e?this.panelAt(this.lastPoint.x,this.lastPoint.y):null;if(this.endPointerDrag(),!e)return;const a=o?.getAttribute("day");a&&this.emitMove(s,this.day,a)};onPointerCancel=()=>{this.pointerDrag?.started||this.endPointerDrag()};scrollFromTouch(t){const r=this.pointerDrag?.startY??t.clientY;let e=t.clientY;this.endPointerDrag(),window.scrollBy(0,r-t.clientY);const s=r=>{r.pointerId===t.pointerId&&(window.scrollBy(0,e-r.clientY),e=r.clientY,r.preventDefault())},o=()=>{window.removeEventListener("pointermove",s),window.removeEventListener("pointerup",o),window.removeEventListener("pointercancel",o)};window.addEventListener("pointermove",s,{passive:!1}),window.addEventListener("pointerup",o),window.addEventListener("pointercancel",o)}cancelHold(){null!==this.holdTimer&&(clearTimeout(this.holdTimer),this.holdTimer=null)}endPointerDrag(){this.cancelHold(),this.stopEdgeScroll(),document.removeEventListener("contextmenu",this.onContextMenuDuringDrag,!0),this.pointerDrag=null,this.draggingId=null,this.clearHighlight(),this.ghost?.remove(),this.ghost=null,this.el.style.removeProperty("touch-action"),window.removeEventListener("pointermove",this.onPointerMove),window.removeEventListener("pointerup",this.onPointerUp),window.removeEventListener("pointercancel",this.onPointerCancel)}startEdgeScroll(){if(null!==this.edgeScrollFrame)return;const r=()=>{if(!this.pointerDrag?.started)return void(this.edgeScrollFrame=null);const e=this.lastPoint.y,s=window.innerHeight;let o=0;if(e<t.EDGE_ZONE?o=-t.EDGE_SPEED*(1-e/t.EDGE_ZONE):e>s-t.EDGE_ZONE&&(o=t.EDGE_SPEED*(1-(s-e)/t.EDGE_ZONE)),0!==o){const t=window.scrollY;window.scrollBy(0,o),window.scrollY!==t&&this.highlightPanelAt(this.lastPoint.x,this.lastPoint.y)}this.edgeScrollFrame=requestAnimationFrame(r)};this.edgeScrollFrame=requestAnimationFrame(r)}stopEdgeScroll(){null!==this.edgeScrollFrame&&(cancelAnimationFrame(this.edgeScrollFrame),this.edgeScrollFrame=null)}panelAt(t,r){this.ghost&&(this.ghost.style.display="none");const e=document.elementFromPoint(t,r);this.ghost&&(this.ghost.style.display="");const s=e?.closest("rp-day-slot");return s||this.nearestPanel(t,r)}nearestPanel(t,r){let e=null,s=1/0;for(const o of Array.from(document.querySelectorAll("rp-day-slot"))){const a=o.getBoundingClientRect();if(0===a.width||0===a.height)continue;const i=Math.hypot(Math.max(a.left-t,0,t-a.right),Math.max(a.top-r,0,r-a.bottom));i<s&&(s=i,e=o)}return s<=64?e:null}highlightPanelAt(t,r){const e=this.panelAt(t,r);e!==this.hoveredPanel&&(this.clearHighlight(),e&&e!==this.el&&(e.querySelector(".slot")?.classList.add("is-drop-active"),this.hoveredPanel=e))}clearHighlight(){this.hoveredPanel?.querySelector(".slot")?.classList.remove("is-drop-active"),this.hoveredPanel=null}cardFor(t){const r=this.normalized.findIndex((r=>r.id===t));return r<0?null:this.el.querySelectorAll(".meal")[r]??null}createGhost(t,r){const e=document.createElement("div");if(e.setAttribute("aria-hidden","true"),e.className="rp-drag-ghost",t){const r=t.getBoundingClientRect();e.style.width=r.width+"px";const s=t.cloneNode(!0);s.classList.remove("is-dragging"),s.removeAttribute("draggable");for(const t of Array.from(s.querySelectorAll("rp-select"))){const r=document.createElement("div");r.className=t.className;const e=t.querySelector(".trigger");e&&r.append(e.cloneNode(!0)),t.replaceWith(r)}for(const t of Array.from(s.querySelectorAll("button, input, select, a")))t.style.pointerEvents="none",t.setAttribute("tabindex","-1");e.append(s)}else e.textContent=r;document.body.append(e),this.ghost=e}moveGhost(t,r){if(!this.ghost)return;const e=this.ghost.getBoundingClientRect(),s=window.innerWidth-e.width+12,o=window.innerHeight-e.height+44;this.ghost.style.transform=`translate(${Math.min(Math.max(t,12),Math.max(s,12))}px, ${Math.min(Math.max(r,44),Math.max(o,44))}px)`}onDrop=t=>{const r=t.dataTransfer?.getData("application/x-rp-meal");if(r){t.preventDefault(),this.dragDepth=0,this.dropActive=!1;try{const{id:t,from:e}=JSON.parse(r);this.emitMove(t,e,this.day)}catch{}}};render(){const t=Array.isArray(this.days)?this.days:[],r=this.dayLabels??{},e=this.normalized;return o(a,{key:"05ee7eff0f1ff19f77363539f3f5ccf2d1d96efb"},o("section",{key:"dce7ecf1d85d7d8cd8b988fb6dc06f93810f532a",class:{slot:!0,"is-drop-active":this.dropActive,"is-empty":0===e.length},onDragEnter:this.onDragEnter,onDragOver:this.onDragOver,onDragLeave:this.onDragLeave,onDrop:this.onDrop},o("header",{key:"086dc84dce8943ae814505878fee4dbc1e3acc1a",class:"head"},o("h3",{key:"a37cb66c77bc30ed80e7eb5d9bbe38c2b2c207b6",class:"day"},this.dayLabel||this.day),o("div",{key:"67e62ed1a5754842f8ffd828ac1ce7cd63a5a666",class:"head-right"},e.length>0&&o("span",{key:"c4460980f7998c355e00ea7d0035297b47a8ecb0",class:"count"},e.length),o("button",{key:"5d4a5c5fafa9e63cf6cd323b0e23cd6354a18d3b",type:"button",class:"add",onClick:()=>this.rpAddMeal.emit(this.day),"aria-label":"Add a meal to "+((this.dayLabels??{})[this.day]||this.dayLabel||this.day)},o("svg",{key:"684fc27b7da23ce41a656bc04524b600dec89ee3",viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},o("path",{key:"c22a9bdbccc3a2fee2f59106371afbfd96c9946f",d:"M12 5v14M5 12h14"}))))),0===e.length?o("div",{class:"empty"},o("slot",null,o("svg",{class:"empty-icon",viewBox:"0 0 24 24",width:"26",height:"26","aria-hidden":"true"},o("path",{d:"M4 4h16v16H4z",opacity:"0.35"}),o("path",{d:"M8 2v4M16 2v4M4 10h16"})),o("p",{class:"empty-text"},"No meals planned"))):o("ul",{class:"meals"},e.map((e=>o("li",{class:{meal:!0,"is-dragging":this.draggingId===e.id},key:e.id,draggable:"touch"!==this.pointerKind,onDragStart:t=>this.onDragStart(t,e),onPointerDown:t=>this.onPointerDown(t,e),onContextMenu:t=>{"touch"===this.pointerKind&&t.preventDefault()}},o("span",{class:"grip","aria-hidden":"true"},o("svg",{viewBox:"0 0 24 24",width:"12",height:"12"},o("circle",{cx:"9",cy:"6",r:"1.4"}),o("circle",{cx:"15",cy:"6",r:"1.4"}),o("circle",{cx:"9",cy:"12",r:"1.4"}),o("circle",{cx:"15",cy:"12",r:"1.4"}),o("circle",{cx:"9",cy:"18",r:"1.4"}),o("circle",{cx:"15",cy:"18",r:"1.4"}))),o("span",{class:"meal-title"},e.title),o("div",{class:"meal-actions"},o("rp-select",{class:"move-select",compact:!0,label:`Move ${e.title} to another day`,placeholder:"Move…",options:t.filter((t=>t!==this.day)).map((t=>({value:t,label:r[t]??t}))),onRpSelectChange:t=>this.emitMove(e.id,this.day,t.detail)}),o("button",{type:"button",class:"remove",onClick:()=>this.rpRemoveMeal.emit({id:e.id,day:this.day}),"aria-label":"Remove "+e.title},o("svg",{viewBox:"0 0 24 24",width:"13",height:"13","aria-hidden":"true"},o("path",{d:"M6 6l12 12M18 6L6 18"}))))))))))}static get style(){return".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-1);align-items:center;justify-content:space-between;padding:var(--rp-space-3) var(--rp-space-2) var(--rp-space-3) 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;touch-action:none;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;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{min-width:0;position:relative;z-index:1;touch-action:manipulation}.remove.sc-rp-day-slot::before{content:'';position:absolute;inset:-9px}.meal.sc-rp-day-slot:has(rp-select[open]),.meals.sc-rp-day-slot:has(rp-select[open]){overflow:visible}.slot.sc-rp-day-slot:has(rp-select[open]){overflow:visible}.meal.sc-rp-day-slot:has(rp-select[open]){z-index:3}.remove.sc-rp-day-slot{display:grid;place-items:center;touch-action:manipulation;position:relative;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}}"}},[774,"rp-day-slot",{day:[513],dayLabel:[1,"day-label"],meals:[16],days:[16],dayLabels:[16],normalized:[32],dropActive:[32],draggingId:[32],pointerKind:[32]}]);function l(){"undefined"!=typeof customElements&&["rp-day-slot","rp-select"].forEach((t=>{switch(t){case"rp-day-slot":customElements.get(r(t))||customElements.define(r(t),n);break;case"rp-select":customElements.get(r(t))||i()}}))}l();const c=n,d=l;export{c as RpDaySlot,d as defineCustomElement}
@@ -1 +1 @@
1
- import{p as r,H as o,c as e,h as a,a as s,t}from"./index.js";const n='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',i=r(class extends o{constructor(r){super(),!1!==r&&this.__registerHost(),this.rpClose=e(this,"rpClose")}get el(){return this}open=!1;heading="";rpClose;previouslyFocused=null;onOpenChange(r){r?(this.previouslyFocused=document.activeElement,document.addEventListener("keydown",this.onKeydown),requestAnimationFrame((()=>this.focusFirstField()))):(document.removeEventListener("keydown",this.onKeydown),this.previouslyFocused?.focus(),this.previouslyFocused=null)}componentDidLoad(){this.open&&this.onOpenChange(!0)}disconnectedCallback(){document.removeEventListener("keydown",this.onKeydown)}async focusFirstField(){const r=this.el.querySelector(n);r?.focus()}onKeydown=r=>{if(this.open)return"Escape"===r.key?(r.preventDefault(),void this.rpClose.emit()):void("Tab"===r.key&&this.trapFocus(r))};trapFocus(r){const o=Array.from(this.el.querySelectorAll(n));if(0===o.length)return;const e=o[0],a=o[o.length-1],s=document.activeElement;r.shiftKey&&s===e?(r.preventDefault(),a.focus()):r.shiftKey||s!==a||(r.preventDefault(),e.focus())}onBackdropClick=r=>{r.target===r.currentTarget&&this.rpClose.emit()};render(){return this.open?a(s,null,a("div",{class:"backdrop",onClick:this.onBackdropClick},a("div",{class:"dialog",role:"dialog","aria-modal":"true","aria-label":this.heading},a("header",{class:"head"},a("h2",{class:"heading"},this.heading),a("button",{type:"button",class:"close",onClick:()=>this.rpClose.emit(),"aria-label":"Close dialog"},a("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},a("path",{d:"M6 6l12 12M18 6L6 18"})))),a("div",{class:"body"},a("slot",null)),a("footer",{class:"foot"},a("slot",{name:"footer"}))))):null}static get watchers(){return{open:[{onOpenChange:0}]}}static get style(){return".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:var(--rp-modal-backdrop, 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}.body.sc-rp-modal:has(rp-select[open]){overflow:visible;position:relative;z-index:1}.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}}"}},[774,"rp-modal",{open:[516],heading:[1],focusFirstField:[64]},void 0,{open:[{onOpenChange:0}]}]);function d(){"undefined"!=typeof customElements&&["rp-modal"].forEach((r=>{"rp-modal"===r&&(customElements.get(t(r))||customElements.define(t(r),i))}))}d();const l=i,p=d;export{l as RpModal,p as defineCustomElement}
1
+ import{p as o,H as r,c as e,h as a,a as t,t as s}from"./index.js";const n='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',d=o(class extends r{constructor(o){super(),!1!==o&&this.__registerHost(),this.rpClose=e(this,"rpClose")}get el(){return this}open=!1;heading="";rpClose;previouslyFocused=null;lockedScrollY=0;onOpenChange(o){o?(this.previouslyFocused=document.activeElement,document.addEventListener("keydown",this.onKeydown),this.lockBackground(),requestAnimationFrame((()=>this.focusFirstField()))):(document.removeEventListener("keydown",this.onKeydown),this.unlockBackground(),this.previouslyFocused?.focus(),this.previouslyFocused=null)}lockBackground(){document.body.dataset.rpModalLock||(this.lockedScrollY=window.scrollY,document.body.dataset.rpModalLock="true",document.body.style.position="fixed",document.body.style.top=`-${this.lockedScrollY}px`,document.body.style.insetInline="0",document.body.style.overflowY="scroll")}unlockBackground(){document.body.dataset.rpModalLock&&(delete document.body.dataset.rpModalLock,document.body.style.removeProperty("position"),document.body.style.removeProperty("top"),document.body.style.removeProperty("inset-inline"),document.body.style.removeProperty("overflow-y"),window.scrollTo(0,this.lockedScrollY))}componentDidLoad(){this.open&&this.onOpenChange(!0)}disconnectedCallback(){document.removeEventListener("keydown",this.onKeydown),this.unlockBackground()}async focusFirstField(){const o=this.el.querySelector(n);o?.focus()}onKeydown=o=>{if(this.open)return"Escape"===o.key?(o.preventDefault(),void this.rpClose.emit()):void("Tab"===o.key&&this.trapFocus(o))};trapFocus(o){const r=Array.from(this.el.querySelectorAll(n));if(0===r.length)return;const e=r[0],a=r[r.length-1],t=document.activeElement;o.shiftKey&&t===e?(o.preventDefault(),a.focus()):o.shiftKey||t!==a||(o.preventDefault(),e.focus())}onBackdropClick=o=>{o.target===o.currentTarget&&this.rpClose.emit()};render(){return this.open?a(t,null,a("div",{class:"backdrop",onClick:this.onBackdropClick},a("div",{class:"dialog",role:"dialog","aria-modal":"true","aria-label":this.heading},a("header",{class:"head"},a("h2",{class:"heading"},this.heading),a("button",{type:"button",class:"close",onClick:()=>this.rpClose.emit(),"aria-label":"Close dialog"},a("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},a("path",{d:"M6 6l12 12M18 6L6 18"})))),a("div",{class:"body"},a("slot",null)),a("footer",{class:"foot"},a("slot",{name:"footer"}))))):null}static get watchers(){return{open:[{onOpenChange:0}]}}static get style(){return".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:var(--rp-modal-backdrop, 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}.body.sc-rp-modal:has(rp-select[open]){overflow:visible;position:relative;z-index:1}.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}}"}},[774,"rp-modal",{open:[516],heading:[1],focusFirstField:[64]},void 0,{open:[{onOpenChange:0}]}]);function i(){"undefined"!=typeof customElements&&["rp-modal"].forEach((o=>{"rp-modal"===o&&(customElements.get(s(o))||customElements.define(s(o),d))}))}i();const c=d,l=i;export{c as RpModal,l as defineCustomElement}
@@ -1 +1 @@
1
- import{S as o,d as s}from"./p-D4hBkDfU.js";const p=o,r=s;export{p as RpSelect,r as defineCustomElement}
1
+ import{S as o,d as s}from"./p-DE3tFqRZ.js";const t=o,p=s;export{t as RpSelect,p as defineCustomElement}
@@ -66,19 +66,59 @@ const Modal = class {
66
66
  /** Fired when the user dismisses the dialog via Escape, the backdrop, or the close button. */
67
67
  rpClose;
68
68
  previouslyFocused = null;
69
+ /** Page offset captured while the background is locked, restored when it is released. */
70
+ lockedScrollY = 0;
69
71
  onOpenChange(isOpen) {
70
72
  if (isOpen) {
71
73
  this.previouslyFocused = document.activeElement;
72
74
  document.addEventListener('keydown', this.onKeydown);
75
+ this.lockBackground();
73
76
  // The dialog content renders in the same tick, so defer focus until it exists.
74
77
  requestAnimationFrame(() => this.focusFirstField());
75
78
  }
76
79
  else {
77
80
  document.removeEventListener('keydown', this.onKeydown);
81
+ this.unlockBackground();
78
82
  this.previouslyFocused?.focus();
79
83
  this.previouslyFocused = null;
80
84
  }
81
85
  }
86
+ /**
87
+ * Freezes the page behind the dialog.
88
+ *
89
+ * Without this the page is still scrollable underneath, and on a phone that is what a
90
+ * touch drag inside the dialog ends up moving: dragging a long option list scrolled the
91
+ * page behind it rather than the list, so the options below the fold were unreachable.
92
+ * `overscroll-behavior` on the list is not enough on its own — it stops a scroll
93
+ * *chaining* outward once the list ends, but not the page claiming the gesture.
94
+ *
95
+ * `position: fixed` rather than `overflow: hidden`, because iOS Safari ignores the
96
+ * latter on `body`. Fixing the body collapses it to the top of the document, so the
97
+ * offset is captured and re-applied as a negative inset, then restored on release —
98
+ * otherwise closing the dialog would jump the page back to the top.
99
+ */
100
+ lockBackground() {
101
+ if (document.body.dataset.rpModalLock)
102
+ return; // A nested dialog must not re-lock.
103
+ this.lockedScrollY = window.scrollY;
104
+ document.body.dataset.rpModalLock = 'true';
105
+ document.body.style.position = 'fixed';
106
+ document.body.style.top = `-${this.lockedScrollY}px`;
107
+ document.body.style.insetInline = '0';
108
+ // The scrollbar disappears with the fixed body; reserving its width stops the page
109
+ // shifting sideways as the dialog opens.
110
+ document.body.style.overflowY = 'scroll';
111
+ }
112
+ unlockBackground() {
113
+ if (!document.body.dataset.rpModalLock)
114
+ return;
115
+ delete document.body.dataset.rpModalLock;
116
+ document.body.style.removeProperty('position');
117
+ document.body.style.removeProperty('top');
118
+ document.body.style.removeProperty('inset-inline');
119
+ document.body.style.removeProperty('overflow-y');
120
+ window.scrollTo(0, this.lockedScrollY);
121
+ }
82
122
  componentDidLoad() {
83
123
  // A dialog can be mounted already open, in which case @Watch never fires.
84
124
  if (this.open)
@@ -87,6 +127,9 @@ const Modal = class {
87
127
  disconnectedCallback() {
88
128
  // Without this, every mount of a page containing a modal leaks a document listener.
89
129
  document.removeEventListener('keydown', this.onKeydown);
130
+ // A dialog unmounted while open would otherwise leave the page frozen with no way
131
+ // back — navigating away with one on screen is the ordinary way that happens.
132
+ this.unlockBackground();
90
133
  }
91
134
  /**
92
135
  * Moves focus to the first focusable control inside the dialog.
@@ -285,8 +328,15 @@ const SearchBar = class {
285
328
  };
286
329
  SearchBar.style = rpSearchBarCss();
287
330
 
288
- const rpSelectCss = () => `.sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;overscroll-behavior:contain;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}`;
331
+ const rpSelectCss = () => `.sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;touch-action:pan-y;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}`;
289
332
 
333
+ /**
334
+ * Movement in CSS pixels that separates a tap on an option from a scroll of the list.
335
+ *
336
+ * Below it the finger was choosing; above it, it was dragging the list and must not select
337
+ * whatever it happens to be over when it lifts.
338
+ */
339
+ const DRAG_SLOP = 10;
290
340
  const Select = class {
291
341
  constructor(hostRef) {
292
342
  registerInstance(this, hostRef);
@@ -325,6 +375,14 @@ const Select = class {
325
375
  rpSelectChange;
326
376
  triggerEl;
327
377
  listEl;
378
+ /**
379
+ * The option a finger is currently resting on, and where it landed.
380
+ *
381
+ * Held between `pointerdown` and `pointerup` so the release can tell a tap from a scroll
382
+ * by how far the finger travelled. Not `@State` — it drives no rendering, and making it
383
+ * reactive would re-render the list on every press.
384
+ */
385
+ pressedOption = null;
328
386
  /** Buffer for type-ahead, cleared after a pause, matching native select behaviour. */
329
387
  typeBuffer = '';
330
388
  typeTimer;
@@ -602,7 +660,7 @@ const Select = class {
602
660
  const selected = this.selectedOption;
603
661
  const listId = 'rp-select-list';
604
662
  const activeId = this.activeIndex >= 0 ? `rp-select-option-${this.activeIndex}` : undefined;
605
- return (h(Host, { key: 'ebc4162f0e81b6d0ff79fd9a0967030ffa01c483' }, h("div", { key: '99ff2315652ccec4f747280754367818ad5a7bae', class: "wrap" }, h("button", { key: '3464c691b00cb4e0b4ffed094209d103cd4ccd36', type: "button", class: "trigger", ref: (element) => (this.triggerEl = element), disabled: this.disabled, role: "combobox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": listId, "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-activedescendant": this.open ? activeId : undefined, onKeyDown: this.onKeyDown,
663
+ return (h(Host, { key: 'ff24ed1943638d0a255238846b55f6a2e0042824' }, h("div", { key: 'e2750500d5d349f64e66e9d9a28d3f5c37ba4e78', class: "wrap" }, h("button", { key: '3ff9611c6f105d1fdc26ca9c332bf2f18efc8983', type: "button", class: "trigger", ref: (element) => (this.triggerEl = element), disabled: this.disabled, role: "combobox", "aria-expanded": this.open ? 'true' : 'false', "aria-controls": listId, "aria-haspopup": "listbox", "aria-label": this.label || undefined, "aria-activedescendant": this.open ? activeId : undefined, onKeyDown: this.onKeyDown,
606
664
  /*
607
665
  Toggled on pointerdown rather than click so one press produces one state
608
666
  change — the document listener that dismisses an open control runs on the
@@ -614,20 +672,47 @@ const Select = class {
614
672
  event.preventDefault();
615
673
  this.triggerEl?.focus();
616
674
  this.open = !this.open;
617
- } }, h("span", { key: '169714fb00d19f3ab58822d113fb994424995e90', class: { 'trigger-value': true, 'is-placeholder': !selected } }, selected?.label ?? this.placeholder), h("svg", { key: '002c4c2783d9f1bc2a3802404e7d16025478f65d', class: "chevron", viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, h("path", { key: 'b5970c61cc218dda77e7cbfebee34e533e76bae2', d: "m6 9 6 6 6-6" }))), this.open && (h("div", { key: '26a3d38fcb704ee018e90fae2601539e04a8fa07', class: "list", id: listId, role: "listbox", tabindex: -1, "aria-label": this.label || undefined, ref: (element) => (this.listEl = element) }, options.length === 0 ? (h("p", { class: "empty" }, "No options")) : (options.map((option, index) => (h("button", { key: option.value, id: `rp-select-option-${index}`, type: "button", role: "option", "aria-selected": option.value === this.value ? 'true' : 'false', class: {
675
+ } }, h("span", { key: '26f8595bad37815f436366c4c3d3fc5a923d7aa5', class: { 'trigger-value': true, 'is-placeholder': !selected } }, selected?.label ?? this.placeholder), h("svg", { key: '782c3417d87d24cfabcc0548d2caf4b604006720', class: "chevron", viewBox: "0 0 24 24", width: "14", height: "14", "aria-hidden": "true" }, h("path", { key: 'f11b0cf117312f97a8e94dbd664f769a542515d9', d: "m6 9 6 6 6-6" }))), this.open && (h("div", { key: '76bca46ff9374b459da8a53881c4672b9db7f4a0', class: "list", id: listId, role: "listbox", tabindex: -1, "aria-label": this.label || undefined, ref: (element) => (this.listEl = element) }, options.length === 0 ? (h("p", { class: "empty" }, "No options")) : (options.map((option, index) => (h("button", { key: option.value, id: `rp-select-option-${index}`, type: "button", role: "option", "aria-selected": option.value === this.value ? 'true' : 'false', class: {
618
676
  option: true,
619
677
  'is-selected': option.value === this.value,
620
678
  'is-active': index === this.activeIndex,
621
679
  }, onPointerDown: (event) => {
622
- // Keeps focus on the trigger; the press is the selection.
680
+ /**
681
+ * A mouse commits on the press, because a press with a mouse is
682
+ * unambiguous and `preventDefault` here is what keeps focus on the
683
+ * trigger rather than moving it to the option.
684
+ *
685
+ * A touch cannot commit yet: the same press is also how the list is
686
+ * scrolled, and committing on contact selected whichever option the
687
+ * finger happened to land on the moment a scroll began. Touch is
688
+ * resolved on release instead, by the handlers below.
689
+ */
690
+ if (event.pointerType !== 'mouse') {
691
+ this.pressedOption = {
692
+ value: option.value,
693
+ x: event.clientX,
694
+ y: event.clientY,
695
+ };
696
+ return;
697
+ }
623
698
  event.preventDefault();
624
- this.choose(option,
625
- // Where to expect the touch's synthetic click, so it can be
626
- // absorbed before it reaches whatever the list was covering.
627
- event.pointerType === 'mouse'
628
- ? undefined
629
- : { x: event.clientX, y: event.clientY });
630
- }, onMouseEnter: () => (this.activeIndex = index) }, h("span", { class: "option-text" }, option.label), option.value === this.value && (h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, h("path", { d: "m5 13 4 4L19 7" }))))))))))));
699
+ this.choose(option);
700
+ }, onPointerUp: (event) => {
701
+ if (event.pointerType === 'mouse')
702
+ return;
703
+ const pressed = this.pressedOption;
704
+ this.pressedOption = null;
705
+ if (!pressed || pressed.value !== option.value)
706
+ return;
707
+ /**
708
+ * Only a finger that stayed put was choosing; one that travelled was
709
+ * scrolling the list, and must not select whatever it ends up over.
710
+ */
711
+ const moved = Math.hypot(event.clientX - pressed.x, event.clientY - pressed.y);
712
+ if (moved > DRAG_SLOP)
713
+ return;
714
+ this.choose(option, { x: event.clientX, y: event.clientY });
715
+ }, onPointerCancel: () => (this.pressedOption = null), onMouseEnter: () => (this.activeIndex = index) }, h("span", { class: "option-text" }, option.label), option.value === this.value && (h("svg", { viewBox: "0 0 24 24", width: "15", height: "15", "aria-hidden": "true" }, h("path", { d: "m5 13 4 4L19 7" }))))))))))));
631
716
  }
632
717
  static get watchers() { return {
633
718
  "open": [{
@@ -0,0 +1 @@
1
+ import{r,c as e,h as a,H as s,g as o}from"./p-xM9qpraa.js";const t=class{constructor(a){r(this,a),this.rpFilterChange=e(this,"rpFilterChange")}options=[];selected=null;label="Filter";rpFilterChange;select(r){this.rpFilterChange.emit(this.selected===r?null:r)}render(){const r=Array.isArray(this.options)?this.options:[];return a(s,{key:"c87ecafe77bff6d1fb9c38911e186ef6c53010d9"},a("div",{key:"a9db225e2972cc98a8e08c2d594b7ec8eb18ae61",class:"chips",role:"group","aria-label":this.label},r.map((r=>a("button",{key:r,type:"button",class:{chip:!0,"is-selected":this.selected===r},"aria-pressed":String(this.selected===r),onClick:()=>this.select(r)},r)))))}};t.style=".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}}";const i=class{constructor(e){r(this,e)}items=[];render(){const r=Array.isArray(this.items)?this.items:[];return a(s,{key:"bac56b8cde1f6366b2000e35974d2d262eac5a34"},a("section",{key:"33c203ac97781768cdeb20e5d0cfa48cc2d7cb1e",class:"wrap"},a("slot",{key:"1b100975a1335b37dfdb893cc67ec6d95c55340c",name:"heading"},a("h2",{key:"1f2d395da7a663bde5fb1bf03bd28c805106bd72",class:"heading"},"Ingredients")),0===r.length?a("p",{class:"empty"},"No ingredients listed for this recipe."):a("ul",{class:"list"},r.map(((r,e)=>a("li",{class:"row",key:`${r.name}-${e}`},a("span",{class:"name"},r.name),a("span",{class:"measure"},r.measure))))),a("div",{key:"d6dcf8d7bab40e3403cc5baaae4e829794232143",class:"note"},a("slot",{key:"6a99c2eca87e8f44e90bb6d5d422cf80a4b1c7af"}))))}};i.style=".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}}";const c='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',n=class{constructor(a){r(this,a),this.rpClose=e(this,"rpClose")}get el(){return o(this)}open=!1;heading="";rpClose;previouslyFocused=null;lockedScrollY=0;onOpenChange(r){r?(this.previouslyFocused=document.activeElement,document.addEventListener("keydown",this.onKeydown),this.lockBackground(),requestAnimationFrame((()=>this.focusFirstField()))):(document.removeEventListener("keydown",this.onKeydown),this.unlockBackground(),this.previouslyFocused?.focus(),this.previouslyFocused=null)}lockBackground(){document.body.dataset.rpModalLock||(this.lockedScrollY=window.scrollY,document.body.dataset.rpModalLock="true",document.body.style.position="fixed",document.body.style.top=`-${this.lockedScrollY}px`,document.body.style.insetInline="0",document.body.style.overflowY="scroll")}unlockBackground(){document.body.dataset.rpModalLock&&(delete document.body.dataset.rpModalLock,document.body.style.removeProperty("position"),document.body.style.removeProperty("top"),document.body.style.removeProperty("inset-inline"),document.body.style.removeProperty("overflow-y"),window.scrollTo(0,this.lockedScrollY))}componentDidLoad(){this.open&&this.onOpenChange(!0)}disconnectedCallback(){document.removeEventListener("keydown",this.onKeydown),this.unlockBackground()}async focusFirstField(){const r=this.el.querySelector(c);r?.focus()}onKeydown=r=>{if(this.open)return"Escape"===r.key?(r.preventDefault(),void this.rpClose.emit()):void("Tab"===r.key&&this.trapFocus(r))};trapFocus(r){const e=Array.from(this.el.querySelectorAll(c));if(0===e.length)return;const a=e[0],s=e[e.length-1],o=document.activeElement;r.shiftKey&&o===a?(r.preventDefault(),s.focus()):r.shiftKey||o!==s||(r.preventDefault(),a.focus())}onBackdropClick=r=>{r.target===r.currentTarget&&this.rpClose.emit()};render(){return this.open?a(s,null,a("div",{class:"backdrop",onClick:this.onBackdropClick},a("div",{class:"dialog",role:"dialog","aria-modal":"true","aria-label":this.heading},a("header",{class:"head"},a("h2",{class:"heading"},this.heading),a("button",{type:"button",class:"close",onClick:()=>this.rpClose.emit(),"aria-label":"Close dialog"},a("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},a("path",{d:"M6 6l12 12M18 6L6 18"})))),a("div",{class:"body"},a("slot",null)),a("footer",{class:"foot"},a("slot",{name:"footer"}))))):null}static get watchers(){return{open:[{onOpenChange:0}]}}};n.style=".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:var(--rp-modal-backdrop, 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}.body.sc-rp-modal:has(rp-select[open]){overflow:visible;position:relative;z-index:1}.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}}";const p=class{constructor(a){r(this,a),this.rpFavoriteToggle=e(this,"rpFavoriteToggle")}get el(){return o(this)}recipeId;recipeTitle;image;category;href;hrefLabel;area;minutes;favorite=!1;imageLoading=!0;imageFailed=!1;pulsing=!1;pulseTimer;rpFavoriteToggle;disconnectedCallback(){clearTimeout(this.pulseTimer)}toggleFavorite=()=>{this.pulsing=!0,clearTimeout(this.pulseTimer),this.pulseTimer=setTimeout((()=>this.pulsing=!1),400),this.rpFavoriteToggle.emit({recipeId:this.recipeId,favorite:!this.favorite})};onImageRef=r=>{r?.complete&&(this.imageLoading=!1)};render(){const r=!0===this.favorite,e=this.image&&!this.imageFailed;return a(s,{key:"5ebbbdda28510540fe58d94e5936c0fdda6bb30f"},a("article",{key:"d5e8f2df7bf56be63708f7b845ab92390ca8c890",class:"card"},a("div",{key:"fcc51c15fa6325dc4e0e99080a5212d0eff56dd9",class:{media:!0,"is-loading":e&&this.imageLoading}},e?a("img",{src:this.image,alt:"",loading:"lazy",width:"320",height:"240",ref:this.onImageRef,onLoad:()=>this.imageLoading=!1,onError:()=>this.imageFailed=!0}):a("div",{class:"media-fallback","aria-hidden":"true"}),a("div",{key:"f734875845b7354091016a125df352c22813fdd4",class:"scrim","aria-hidden":"true"}),a("div",{key:"d9adaa68e15ba279e782732be0c8469656e05a13",class:"badges"},a("slot",{key:"1115a3ba435e26b0b7ca04144722bf4f6732fc9c"})),a("button",{key:"3c3b1f4822e17f02096a004b4da9ad7b5b83d763",type:"button",class:{favorite:!0,"is-pulsing":this.pulsing},onClick:this.toggleFavorite,"aria-pressed":r?"true":"false","aria-label":r?`Remove ${this.recipeTitle} from favorites`:`Add ${this.recipeTitle} to favorites`},a("svg",{key:"1d3895443869e4962d27ad56cbdb0c13c9d6a757",viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true"},a("path",{key:"01d40fc3bfcc511ff532e1e7eb54892d89236eb7",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"})))),this.href&&a("a",{key:"371d1e65eac91bebed9d153ce5478c9af95a2aef",class:"cover-link",href:this.href},a("span",{key:"5161a6b3ac5298a70d234b054c5e1605ef7268ab",class:"sr-only"},this.hrefLabel??this.recipeTitle)),a("div",{key:"5697df4daea43b488813033ad8921a201e6fd1c0",class:"body"},a("h3",{key:"ed3e24ad4b80d14b91869f12253d970de66f053b",class:"title"},this.recipeTitle),a("div",{key:"2bf4fc90966b0bb4dac79713fc2cbe57ff16bcc0",class:"meta"},this.category&&a("span",{key:"56fcda921b9a905065d09f94e72592a99b275db4",class:"pill pill-category"},this.category),this.area&&a("span",{key:"0d2931d3b84e3c45069a419ae4ca354d88dc4900",class:"pill"},this.area),this.minutes?a("span",{class:"pill"},this.minutes," min"):null)),a("div",{key:"6459a7aec703fcb5503167bfde35cd9b9ab0f120",class:"actions"},a("slot",{key:"0b09ea038f33db09046481c61bc1ee6d14cf1110",name:"actions"}))))}};p.style=".sc-rp-recipe-card-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.card.sc-rp-recipe-card{position:relative;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)}.cover-link.sc-rp-recipe-card{position:absolute;inset:0;z-index:1;border-radius:inherit}.actions.sc-rp-recipe-card{position:relative}.favorite.sc-rp-recipe-card,.actions.sc-rp-recipe-card,.badges.sc-rp-recipe-card{z-index:2}.cover-link.sc-rp-recipe-card:focus-visible{outline:var(--rp-focus-ring);outline-offset:-2px}.sr-only.sc-rp-recipe-card{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.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%, var(--rp-card-fallback-sheen, rgb(255 255 255 / 0.55)), transparent 55%), linear-gradient( 135deg, var(--rp-card-fallback-from, var(--rp-caramel-100)), var(--rp-card-fallback-to, 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:var(--rp-card-favorite-bg, rgb(255 255 255 / 0.82));backdrop-filter:blur(8px);border:1px solid var(--rp-card-favorite-border, 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-card-favorite-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-strong)}[favorite].sc-rp-recipe-card-h .favorite.sc-rp-recipe-card:hover svg.sc-rp-recipe-card{fill:var(--rp-color-favorite-strong)}.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;flex-wrap:wrap;gap:var(--rp-space-2);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)}}.favorite.is-pulsing.sc-rp-recipe-card svg.sc-rp-recipe-card{animation:rp-heart-beat 400ms var(--rp-ease);transform-origin:center}@keyframes rp-heart-beat{0%{transform:scale(1)}30%{transform:scale(0.7)}55%{transform:scale(1.35)}75%{transform:scale(0.94)}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}}";const d=class{constructor(a){r(this,a),this.rpSearch=e(this,"rpSearch"),this.rpClear=e(this,"rpClear")}value="";placeholder="Search recipes";label="Search recipes";draft="";rpSearch;rpClear;onValueChange(r){this.draft=r??""}componentWillLoad(){this.draft=this.value??""}onSubmit=r=>{r.preventDefault(),this.rpSearch.emit(this.draft.trim())};onInput=r=>{this.draft=r.target.value};onClear=()=>{this.draft="",this.rpClear.emit()};render(){return a(s,{key:"98c0c2367f27c061759b4fcae36b09fb4f88a720"},a("form",{key:"de043755e60e10f39b102605b5347416abf9dc8f",class:"bar",role:"search",onSubmit:this.onSubmit},a("svg",{key:"f5fdf365cd2901deb885068afece74c843a9d174",class:"icon",viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true"},a("circle",{key:"9ad873f8544081cbd16f7666e428565ade2cdbed",cx:"11",cy:"11",r:"7"}),a("path",{key:"d6284fb25056636002e6cde74a1bd7bf36f40291",d:"m20 20-3.6-3.6"})),a("input",{key:"17288bc6a472a736d78d8beef70316547c7eb11f",type:"search",class:"field",value:this.draft,placeholder:this.placeholder,"aria-label":this.label,onInput:this.onInput}),this.draft&&a("button",{key:"468a3c549bad63863a6bce18d0d46335705ace89",type:"button",class:"clear",onClick:this.onClear,"aria-label":"Clear search"},a("svg",{key:"70bab6cfdea49c209208e19a496ab24429bf704e",viewBox:"0 0 24 24",width:"14",height:"14","aria-hidden":"true"},a("path",{key:"dcafa21163e380fed6ff35dff0e8f1915b7d5500",d:"M6 6l12 12M18 6L6 18"}))),a("button",{key:"24ac96852bb46844121597ee647c5e35304b9df9",type:"submit",class:"submit","aria-label":"Search"},a("span",{key:"d6e9577315a844403e120fb705a180f49c8f5733",class:"submit-text"},"Search"),a("svg",{key:"9fa48cfa05c8d8a3b5f328131c12a5b954069e56",class:"submit-icon",viewBox:"0 0 24 24",width:"17",height:"17","aria-hidden":"true"},a("circle",{key:"e9367a2e0ee4e05f3b39cbd728f2ea968a1c129f",cx:"11",cy:"11",r:"7"}),a("path",{key:"f2f41503b77ae140224746a419f792ceb77ea5ff",d:"m20 20-3.6-3.6"})))))}static get watchers(){return{value:[{onValueChange:0}]}}};d.style=".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)}.submit-icon.sc-rp-search-bar{display:none;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}.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: 560px){.bar.sc-rp-search-bar{padding-inline-start:var(--rp-space-3);gap:var(--rp-space-1)}.submit.sc-rp-search-bar{display:grid;place-items:center;width:38px;height:38px;padding:0}.submit-text.sc-rp-search-bar{display:none}.submit-icon.sc-rp-search-bar{display:block}}@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}}";const l=class{constructor(a){r(this,a),this.rpSelectChange=e(this,"rpSelectChange")}get el(){return o(this)}options=[];value="";label="";placeholder="Choose…";open=!1;disabled=!1;compact=!1;dropUp=!1;activeIndex=-1;rpSelectChange;triggerEl;listEl;pressedOption=null;typeBuffer="";typeTimer;onOpenChange(r){if(!r)return window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0),this.el.style.removeProperty("--rp-select-max-height"),void(this.dropUp=!1);this.activeIndex=Math.max(0,this.normalizedOptions.findIndex((r=>r.value===this.value))),requestAnimationFrame((()=>requestAnimationFrame((()=>{this.position(),this.scrollActiveIntoView()})))),window.addEventListener("resize",this.position),window.addEventListener("scroll",this.onAncestorScroll,!0)}onOptionsChange(){this.open&&requestAnimationFrame((()=>requestAnimationFrame((()=>this.position()))))}disconnectedCallback(){clearTimeout(this.typeTimer),window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0)}onAncestorScroll=r=>{r.target!==this.listEl&&this.position()};position=()=>{if(!this.open||!this.triggerEl)return;const r=this.triggerEl.getBoundingClientRect(),e=this.clippingBounds(),a=Math.min(window.innerHeight,e.bottom),s=Math.max(0,e.top),o=a-r.bottom-8-12,t=r.top-s-8-12,i=o<(this.listEl?Math.min(260,this.listEl.scrollHeight):Math.min(260,40*this.normalizedOptions.length+8))&&t>o;this.dropUp=i;const c=Math.max(96,Math.floor(i?t:o));this.el.style.setProperty("--rp-select-max-height",`${c}px`)};clippingBounds(){let r=this.el.parentElement;for(;r&&r!==document.body;){const e=getComputedStyle(r);if("visible"!==e.overflow&&"visible"!==e.overflowY){const e=r.getBoundingClientRect();if(e.height>0)return{top:e.top,bottom:e.bottom}}r=r.parentElement}return{top:0,bottom:window.innerHeight}}async focusControl(){this.triggerEl?.focus()}onDocumentPointerDown(r){this.open&&(this.el.contains(r.target)||(this.open=!1))}get normalizedOptions(){return Array.isArray(this.options)?this.options:[]}get selectedOption(){return this.normalizedOptions.find((r=>r.value===this.value))}choose(r,e){this.value=r.value,this.open=!1,this.rpSelectChange.emit(r.value),this.triggerEl?.focus(),e&&this.swallowGhostClick(e.x,e.y)}swallowGhostClick(r,e){const a=a=>{Math.hypot(a.clientX-r,a.clientY-e)>24||(a.preventDefault(),a.stopPropagation(),s())},s=()=>{window.clearTimeout(o),document.removeEventListener("click",a,!0)};document.addEventListener("click",a,!0);const o=window.setTimeout(s,500)}scrollActiveIntoView(){const r=this.listEl?.querySelector(".option.is-active");r?.scrollIntoView({block:"nearest"})}move(r){const e=this.normalizedOptions;if(0===e.length)return;const a=this.activeIndex+r;this.activeIndex=a<0?e.length-1:a%e.length,requestAnimationFrame((()=>this.scrollActiveIntoView()))}typeAhead(r){clearTimeout(this.typeTimer),this.typeBuffer+=r.toLowerCase(),this.typeTimer=setTimeout((()=>this.typeBuffer=""),600);const e=this.normalizedOptions.findIndex((r=>r.label.toLowerCase().startsWith(this.typeBuffer)));-1!==e&&(this.open?(this.activeIndex=e,requestAnimationFrame((()=>this.scrollActiveIntoView()))):this.choose(this.normalizedOptions[e]))}onKeyDown=r=>{if(!this.disabled)switch(r.key){case"ArrowDown":return r.preventDefault(),void(this.open?this.move(1):this.open=!0);case"ArrowUp":return r.preventDefault(),void(this.open?this.move(-1):this.open=!0);case"Home":if(!this.open)return;return r.preventDefault(),this.activeIndex=0,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"End":if(!this.open)return;return r.preventDefault(),this.activeIndex=this.normalizedOptions.length-1,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"Enter":case" ":return r.preventDefault(),void(this.open?this.activeIndex>=0&&this.choose(this.normalizedOptions[this.activeIndex]):this.open=!0);case"Escape":if(!this.open)return;return r.preventDefault(),void(this.open=!1);case"Tab":return void(this.open=!1);default:1!==r.key.length||r.metaKey||r.ctrlKey||r.altKey||(r.preventDefault(),this.typeAhead(r.key))}};render(){const r=this.normalizedOptions,e=this.selectedOption,o="rp-select-list";return a(s,{key:"ff24ed1943638d0a255238846b55f6a2e0042824"},a("div",{key:"e2750500d5d349f64e66e9d9a28d3f5c37ba4e78",class:"wrap"},a("button",{key:"3ff9611c6f105d1fdc26ca9c332bf2f18efc8983",type:"button",class:"trigger",ref:r=>this.triggerEl=r,disabled:this.disabled,role:"combobox","aria-expanded":this.open?"true":"false","aria-controls":o,"aria-haspopup":"listbox","aria-label":this.label||void 0,"aria-activedescendant":this.open&&this.activeIndex>=0?`rp-select-option-${this.activeIndex}`:void 0,onKeyDown:this.onKeyDown,onPointerDown:r=>{this.disabled||(r.preventDefault(),this.triggerEl?.focus(),this.open=!this.open)}},a("span",{key:"26f8595bad37815f436366c4c3d3fc5a923d7aa5",class:{"trigger-value":!0,"is-placeholder":!e}},e?.label??this.placeholder),a("svg",{key:"782c3417d87d24cfabcc0548d2caf4b604006720",class:"chevron",viewBox:"0 0 24 24",width:"14",height:"14","aria-hidden":"true"},a("path",{key:"f11b0cf117312f97a8e94dbd664f769a542515d9",d:"m6 9 6 6 6-6"}))),this.open&&a("div",{key:"76bca46ff9374b459da8a53881c4672b9db7f4a0",class:"list",id:o,role:"listbox",tabindex:-1,"aria-label":this.label||void 0,ref:r=>this.listEl=r},0===r.length?a("p",{class:"empty"},"No options"):r.map(((r,e)=>a("button",{key:r.value,id:`rp-select-option-${e}`,type:"button",role:"option","aria-selected":r.value===this.value?"true":"false",class:{option:!0,"is-selected":r.value===this.value,"is-active":e===this.activeIndex},onPointerDown:e=>{"mouse"===e.pointerType?(e.preventDefault(),this.choose(r)):this.pressedOption={value:r.value,x:e.clientX,y:e.clientY}},onPointerUp:e=>{if("mouse"===e.pointerType)return;const a=this.pressedOption;this.pressedOption=null,a&&a.value===r.value&&(Math.hypot(e.clientX-a.x,e.clientY-a.y)>10||this.choose(r,{x:e.clientX,y:e.clientY}))},onPointerCancel:()=>this.pressedOption=null,onMouseEnter:()=>this.activeIndex=e},a("span",{class:"option-text"},r.label),r.value===this.value&&a("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},a("path",{d:"m5 13 4 4L19 7"}))))))))}static get watchers(){return{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}}};l.style=".sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;touch-action:pan-y;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}";export{t as rp_filter_chips,i as rp_ingredient_list,n as rp_modal,p as rp_recipe_card,d as rp_search_bar,l as rp_select}
@@ -1 +1 @@
1
- import{p as e,b as a}from"./p-xM9qpraa.js";export{s as setNonce}from"./p-xM9qpraa.js";import{g as o}from"./p-DQuL1Twl.js";(()=>{const a=import.meta.url,o={};return""!==a&&(o.resourcesUrl=new URL(".",a).href),e(o)})().then((async e=>(await o(),a([["p-b3485d04",[[774,"rp-day-slot",{day:[513],dayLabel:[1,"day-label"],meals:[16],days:[16],dayLabels:[16],normalized:[32],dropActive:[32],draggingId:[32],pointerKind:[32]}]]],["p-7a8ee97f",[[514,"rp-filter-menu",{label:[1],options:[16],selected:[1],searchPlaceholder:[1,"search-placeholder"],searchable:[4],open:[1540],filterText:[32],activeIndex:[32]},[[5,"pointerdown","onDocumentPointerDown"],[4,"keydown","onDocumentKeydown"]],{open:[{onOpenChange:0}]}]]],["p-71d7a961",[[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],href:[1],hrefLabel:[1,"href-label"],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}]}],[514,"rp-select",{options:[16],value:[1025],label:[1],placeholder:[1],open:[1540],disabled:[516],compact:[516],dropUp:[1540,"drop-up"],activeIndex:[32],focusControl:[64]},[[5,"pointerdown","onDocumentPointerDown"]],{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}]]]],e))));
1
+ import{p as e,b as a}from"./p-xM9qpraa.js";export{s as setNonce}from"./p-xM9qpraa.js";import{g as o}from"./p-DQuL1Twl.js";(()=>{const a=import.meta.url,o={};return""!==a&&(o.resourcesUrl=new URL(".",a).href),e(o)})().then((async e=>(await o(),a([["p-b3485d04",[[774,"rp-day-slot",{day:[513],dayLabel:[1,"day-label"],meals:[16],days:[16],dayLabels:[16],normalized:[32],dropActive:[32],draggingId:[32],pointerKind:[32]}]]],["p-7a8ee97f",[[514,"rp-filter-menu",{label:[1],options:[16],selected:[1],searchPlaceholder:[1,"search-placeholder"],searchable:[4],open:[1540],filterText:[32],activeIndex:[32]},[[5,"pointerdown","onDocumentPointerDown"],[4,"keydown","onDocumentKeydown"]],{open:[{onOpenChange:0}]}]]],["p-22441648",[[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],href:[1],hrefLabel:[1,"href-label"],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}]}],[514,"rp-select",{options:[16],value:[1025],label:[1],placeholder:[1],open:[1540],disabled:[516],compact:[516],dropUp:[1540,"drop-up"],activeIndex:[32],focusControl:[64]},[[5,"pointerdown","onDocumentPointerDown"]],{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}]]]],e))));
@@ -17,7 +17,25 @@ export declare class Modal {
17
17
  /** Fired when the user dismisses the dialog via Escape, the backdrop, or the close button. */
18
18
  rpClose: EventEmitter<void>;
19
19
  private previouslyFocused;
20
+ /** Page offset captured while the background is locked, restored when it is released. */
21
+ private lockedScrollY;
20
22
  onOpenChange(isOpen: boolean): void;
23
+ /**
24
+ * Freezes the page behind the dialog.
25
+ *
26
+ * Without this the page is still scrollable underneath, and on a phone that is what a
27
+ * touch drag inside the dialog ends up moving: dragging a long option list scrolled the
28
+ * page behind it rather than the list, so the options below the fold were unreachable.
29
+ * `overscroll-behavior` on the list is not enough on its own — it stops a scroll
30
+ * *chaining* outward once the list ends, but not the page claiming the gesture.
31
+ *
32
+ * `position: fixed` rather than `overflow: hidden`, because iOS Safari ignores the
33
+ * latter on `body`. Fixing the body collapses it to the top of the document, so the
34
+ * offset is captured and re-applied as a negative inset, then restored on release —
35
+ * otherwise closing the dialog would jump the page back to the top.
36
+ */
37
+ private lockBackground;
38
+ private unlockBackground;
21
39
  componentDidLoad(): void;
22
40
  disconnectedCallback(): void;
23
41
  /**
@@ -52,6 +52,14 @@ export declare class Select {
52
52
  rpSelectChange: EventEmitter<string>;
53
53
  private triggerEl?;
54
54
  private listEl?;
55
+ /**
56
+ * The option a finger is currently resting on, and where it landed.
57
+ *
58
+ * Held between `pointerdown` and `pointerup` so the release can tell a tap from a scroll
59
+ * by how far the finger travelled. Not `@State` — it drives no rendering, and making it
60
+ * reactive would re-render the list on every press.
61
+ */
62
+ private pressedOption;
55
63
  /** Buffer for type-ahead, cleared after a pause, matching native select behaviour. */
56
64
  private typeBuffer;
57
65
  private typeTimer?;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recipe-planner-ui",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Framework-agnostic web components for recipe discovery and meal planning UIs.",
5
5
  "license": "MIT",
6
6
  "author": "sahilsoni432",
@@ -1 +0,0 @@
1
- import{p as e,H as t,c as r,h as s,a as o,t as i}from"./index.js";const a=e(class extends t{constructor(e){super(),!1!==e&&this.__registerHost(),this.rpSelectChange=r(this,"rpSelectChange")}get el(){return this}options=[];value="";label="";placeholder="Choose…";open=!1;disabled=!1;compact=!1;dropUp=!1;activeIndex=-1;rpSelectChange;triggerEl;listEl;typeBuffer="";typeTimer;onOpenChange(e){if(!e)return window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0),this.el.style.removeProperty("--rp-select-max-height"),void(this.dropUp=!1);this.activeIndex=Math.max(0,this.normalizedOptions.findIndex((e=>e.value===this.value))),requestAnimationFrame((()=>requestAnimationFrame((()=>{this.position(),this.scrollActiveIntoView()})))),window.addEventListener("resize",this.position),window.addEventListener("scroll",this.onAncestorScroll,!0)}onOptionsChange(){this.open&&requestAnimationFrame((()=>requestAnimationFrame((()=>this.position()))))}disconnectedCallback(){clearTimeout(this.typeTimer),window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0)}onAncestorScroll=e=>{e.target!==this.listEl&&this.position()};position=()=>{if(!this.open||!this.triggerEl)return;const e=this.triggerEl.getBoundingClientRect(),t=this.clippingBounds(),r=Math.min(window.innerHeight,t.bottom),s=Math.max(0,t.top),o=r-e.bottom-8-12,i=e.top-s-8-12,a=o<(this.listEl?Math.min(260,this.listEl.scrollHeight):Math.min(260,40*this.normalizedOptions.length+8))&&i>o;this.dropUp=a;const n=Math.max(96,Math.floor(a?i:o));this.el.style.setProperty("--rp-select-max-height",`${n}px`)};clippingBounds(){let e=this.el.parentElement;for(;e&&e!==document.body;){const t=getComputedStyle(e);if("visible"!==t.overflow&&"visible"!==t.overflowY){const t=e.getBoundingClientRect();if(t.height>0)return{top:t.top,bottom:t.bottom}}e=e.parentElement}return{top:0,bottom:window.innerHeight}}async focusControl(){this.triggerEl?.focus()}onDocumentPointerDown(e){this.open&&(this.el.contains(e.target)||(this.open=!1))}get normalizedOptions(){return Array.isArray(this.options)?this.options:[]}get selectedOption(){return this.normalizedOptions.find((e=>e.value===this.value))}choose(e,t){this.value=e.value,this.open=!1,this.rpSelectChange.emit(e.value),this.triggerEl?.focus(),t&&this.swallowGhostClick(t.x,t.y)}swallowGhostClick(e,t){const r=r=>{Math.hypot(r.clientX-e,r.clientY-t)>24||(r.preventDefault(),r.stopPropagation(),s())},s=()=>{window.clearTimeout(o),document.removeEventListener("click",r,!0)};document.addEventListener("click",r,!0);const o=window.setTimeout(s,500)}scrollActiveIntoView(){const e=this.listEl?.querySelector(".option.is-active");e?.scrollIntoView({block:"nearest"})}move(e){const t=this.normalizedOptions;if(0===t.length)return;const r=this.activeIndex+e;this.activeIndex=r<0?t.length-1:r%t.length,requestAnimationFrame((()=>this.scrollActiveIntoView()))}typeAhead(e){clearTimeout(this.typeTimer),this.typeBuffer+=e.toLowerCase(),this.typeTimer=setTimeout((()=>this.typeBuffer=""),600);const t=this.normalizedOptions.findIndex((e=>e.label.toLowerCase().startsWith(this.typeBuffer)));-1!==t&&(this.open?(this.activeIndex=t,requestAnimationFrame((()=>this.scrollActiveIntoView()))):this.choose(this.normalizedOptions[t]))}onKeyDown=e=>{if(!this.disabled)switch(e.key){case"ArrowDown":return e.preventDefault(),void(this.open?this.move(1):this.open=!0);case"ArrowUp":return e.preventDefault(),void(this.open?this.move(-1):this.open=!0);case"Home":if(!this.open)return;return e.preventDefault(),this.activeIndex=0,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"End":if(!this.open)return;return e.preventDefault(),this.activeIndex=this.normalizedOptions.length-1,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"Enter":case" ":return e.preventDefault(),void(this.open?this.activeIndex>=0&&this.choose(this.normalizedOptions[this.activeIndex]):this.open=!0);case"Escape":if(!this.open)return;return e.preventDefault(),void(this.open=!1);case"Tab":return void(this.open=!1);default:1!==e.key.length||e.metaKey||e.ctrlKey||e.altKey||(e.preventDefault(),this.typeAhead(e.key))}};render(){const e=this.normalizedOptions,t=this.selectedOption,r="rp-select-list";return s(o,{key:"ebc4162f0e81b6d0ff79fd9a0967030ffa01c483"},s("div",{key:"99ff2315652ccec4f747280754367818ad5a7bae",class:"wrap"},s("button",{key:"3464c691b00cb4e0b4ffed094209d103cd4ccd36",type:"button",class:"trigger",ref:e=>this.triggerEl=e,disabled:this.disabled,role:"combobox","aria-expanded":this.open?"true":"false","aria-controls":r,"aria-haspopup":"listbox","aria-label":this.label||void 0,"aria-activedescendant":this.open&&this.activeIndex>=0?`rp-select-option-${this.activeIndex}`:void 0,onKeyDown:this.onKeyDown,onPointerDown:e=>{this.disabled||(e.preventDefault(),this.triggerEl?.focus(),this.open=!this.open)}},s("span",{key:"169714fb00d19f3ab58822d113fb994424995e90",class:{"trigger-value":!0,"is-placeholder":!t}},t?.label??this.placeholder),s("svg",{key:"002c4c2783d9f1bc2a3802404e7d16025478f65d",class:"chevron",viewBox:"0 0 24 24",width:"14",height:"14","aria-hidden":"true"},s("path",{key:"b5970c61cc218dda77e7cbfebee34e533e76bae2",d:"m6 9 6 6 6-6"}))),this.open&&s("div",{key:"26a3d38fcb704ee018e90fae2601539e04a8fa07",class:"list",id:r,role:"listbox",tabindex:-1,"aria-label":this.label||void 0,ref:e=>this.listEl=e},0===e.length?s("p",{class:"empty"},"No options"):e.map(((e,t)=>s("button",{key:e.value,id:`rp-select-option-${t}`,type:"button",role:"option","aria-selected":e.value===this.value?"true":"false",class:{option:!0,"is-selected":e.value===this.value,"is-active":t===this.activeIndex},onPointerDown:t=>{t.preventDefault(),this.choose(e,"mouse"===t.pointerType?void 0:{x:t.clientX,y:t.clientY})},onMouseEnter:()=>this.activeIndex=t},s("span",{class:"option-text"},e.label),e.value===this.value&&s("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},s("path",{d:"m5 13 4 4L19 7"}))))))))}static get watchers(){return{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}}static get style(){return".sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;overscroll-behavior:contain;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}"}},[514,"rp-select",{options:[16],value:[1025],label:[1],placeholder:[1],open:[1540],disabled:[516],compact:[516],dropUp:[1540,"drop-up"],activeIndex:[32],focusControl:[64]},[[5,"pointerdown","onDocumentPointerDown"]],{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}]);function n(){"undefined"!=typeof customElements&&["rp-select"].forEach((e=>{"rp-select"===e&&(customElements.get(i(e))||customElements.define(i(e),a))}))}n();export{a as S,n as d}
@@ -1 +0,0 @@
1
- import{r,c as e,h as a,H as s,g as o}from"./p-xM9qpraa.js";const t=class{constructor(a){r(this,a),this.rpFilterChange=e(this,"rpFilterChange")}options=[];selected=null;label="Filter";rpFilterChange;select(r){this.rpFilterChange.emit(this.selected===r?null:r)}render(){const r=Array.isArray(this.options)?this.options:[];return a(s,{key:"c87ecafe77bff6d1fb9c38911e186ef6c53010d9"},a("div",{key:"a9db225e2972cc98a8e08c2d594b7ec8eb18ae61",class:"chips",role:"group","aria-label":this.label},r.map((r=>a("button",{key:r,type:"button",class:{chip:!0,"is-selected":this.selected===r},"aria-pressed":String(this.selected===r),onClick:()=>this.select(r)},r)))))}};t.style=".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}}";const i=class{constructor(e){r(this,e)}items=[];render(){const r=Array.isArray(this.items)?this.items:[];return a(s,{key:"bac56b8cde1f6366b2000e35974d2d262eac5a34"},a("section",{key:"33c203ac97781768cdeb20e5d0cfa48cc2d7cb1e",class:"wrap"},a("slot",{key:"1b100975a1335b37dfdb893cc67ec6d95c55340c",name:"heading"},a("h2",{key:"1f2d395da7a663bde5fb1bf03bd28c805106bd72",class:"heading"},"Ingredients")),0===r.length?a("p",{class:"empty"},"No ingredients listed for this recipe."):a("ul",{class:"list"},r.map(((r,e)=>a("li",{class:"row",key:`${r.name}-${e}`},a("span",{class:"name"},r.name),a("span",{class:"measure"},r.measure))))),a("div",{key:"d6dcf8d7bab40e3403cc5baaae4e829794232143",class:"note"},a("slot",{key:"6a99c2eca87e8f44e90bb6d5d422cf80a4b1c7af"}))))}};i.style=".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}}";const c='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',n=class{constructor(a){r(this,a),this.rpClose=e(this,"rpClose")}get el(){return o(this)}open=!1;heading="";rpClose;previouslyFocused=null;onOpenChange(r){r?(this.previouslyFocused=document.activeElement,document.addEventListener("keydown",this.onKeydown),requestAnimationFrame((()=>this.focusFirstField()))):(document.removeEventListener("keydown",this.onKeydown),this.previouslyFocused?.focus(),this.previouslyFocused=null)}componentDidLoad(){this.open&&this.onOpenChange(!0)}disconnectedCallback(){document.removeEventListener("keydown",this.onKeydown)}async focusFirstField(){const r=this.el.querySelector(c);r?.focus()}onKeydown=r=>{if(this.open)return"Escape"===r.key?(r.preventDefault(),void this.rpClose.emit()):void("Tab"===r.key&&this.trapFocus(r))};trapFocus(r){const e=Array.from(this.el.querySelectorAll(c));if(0===e.length)return;const a=e[0],s=e[e.length-1],o=document.activeElement;r.shiftKey&&o===a?(r.preventDefault(),s.focus()):r.shiftKey||o!==s||(r.preventDefault(),a.focus())}onBackdropClick=r=>{r.target===r.currentTarget&&this.rpClose.emit()};render(){return this.open?a(s,null,a("div",{class:"backdrop",onClick:this.onBackdropClick},a("div",{class:"dialog",role:"dialog","aria-modal":"true","aria-label":this.heading},a("header",{class:"head"},a("h2",{class:"heading"},this.heading),a("button",{type:"button",class:"close",onClick:()=>this.rpClose.emit(),"aria-label":"Close dialog"},a("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},a("path",{d:"M6 6l12 12M18 6L6 18"})))),a("div",{class:"body"},a("slot",null)),a("footer",{class:"foot"},a("slot",{name:"footer"}))))):null}static get watchers(){return{open:[{onOpenChange:0}]}}};n.style=".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:var(--rp-modal-backdrop, 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}.body.sc-rp-modal:has(rp-select[open]){overflow:visible;position:relative;z-index:1}.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}}";const p=class{constructor(a){r(this,a),this.rpFavoriteToggle=e(this,"rpFavoriteToggle")}get el(){return o(this)}recipeId;recipeTitle;image;category;href;hrefLabel;area;minutes;favorite=!1;imageLoading=!0;imageFailed=!1;pulsing=!1;pulseTimer;rpFavoriteToggle;disconnectedCallback(){clearTimeout(this.pulseTimer)}toggleFavorite=()=>{this.pulsing=!0,clearTimeout(this.pulseTimer),this.pulseTimer=setTimeout((()=>this.pulsing=!1),400),this.rpFavoriteToggle.emit({recipeId:this.recipeId,favorite:!this.favorite})};onImageRef=r=>{r?.complete&&(this.imageLoading=!1)};render(){const r=!0===this.favorite,e=this.image&&!this.imageFailed;return a(s,{key:"5ebbbdda28510540fe58d94e5936c0fdda6bb30f"},a("article",{key:"d5e8f2df7bf56be63708f7b845ab92390ca8c890",class:"card"},a("div",{key:"fcc51c15fa6325dc4e0e99080a5212d0eff56dd9",class:{media:!0,"is-loading":e&&this.imageLoading}},e?a("img",{src:this.image,alt:"",loading:"lazy",width:"320",height:"240",ref:this.onImageRef,onLoad:()=>this.imageLoading=!1,onError:()=>this.imageFailed=!0}):a("div",{class:"media-fallback","aria-hidden":"true"}),a("div",{key:"f734875845b7354091016a125df352c22813fdd4",class:"scrim","aria-hidden":"true"}),a("div",{key:"d9adaa68e15ba279e782732be0c8469656e05a13",class:"badges"},a("slot",{key:"1115a3ba435e26b0b7ca04144722bf4f6732fc9c"})),a("button",{key:"3c3b1f4822e17f02096a004b4da9ad7b5b83d763",type:"button",class:{favorite:!0,"is-pulsing":this.pulsing},onClick:this.toggleFavorite,"aria-pressed":r?"true":"false","aria-label":r?`Remove ${this.recipeTitle} from favorites`:`Add ${this.recipeTitle} to favorites`},a("svg",{key:"1d3895443869e4962d27ad56cbdb0c13c9d6a757",viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true"},a("path",{key:"01d40fc3bfcc511ff532e1e7eb54892d89236eb7",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"})))),this.href&&a("a",{key:"371d1e65eac91bebed9d153ce5478c9af95a2aef",class:"cover-link",href:this.href},a("span",{key:"5161a6b3ac5298a70d234b054c5e1605ef7268ab",class:"sr-only"},this.hrefLabel??this.recipeTitle)),a("div",{key:"5697df4daea43b488813033ad8921a201e6fd1c0",class:"body"},a("h3",{key:"ed3e24ad4b80d14b91869f12253d970de66f053b",class:"title"},this.recipeTitle),a("div",{key:"2bf4fc90966b0bb4dac79713fc2cbe57ff16bcc0",class:"meta"},this.category&&a("span",{key:"56fcda921b9a905065d09f94e72592a99b275db4",class:"pill pill-category"},this.category),this.area&&a("span",{key:"0d2931d3b84e3c45069a419ae4ca354d88dc4900",class:"pill"},this.area),this.minutes?a("span",{class:"pill"},this.minutes," min"):null)),a("div",{key:"6459a7aec703fcb5503167bfde35cd9b9ab0f120",class:"actions"},a("slot",{key:"0b09ea038f33db09046481c61bc1ee6d14cf1110",name:"actions"}))))}};p.style=".sc-rp-recipe-card-h{display:block;font-family:var(--rp-font-sans);color:var(--rp-color-text)}.card.sc-rp-recipe-card{position:relative;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)}.cover-link.sc-rp-recipe-card{position:absolute;inset:0;z-index:1;border-radius:inherit}.actions.sc-rp-recipe-card{position:relative}.favorite.sc-rp-recipe-card,.actions.sc-rp-recipe-card,.badges.sc-rp-recipe-card{z-index:2}.cover-link.sc-rp-recipe-card:focus-visible{outline:var(--rp-focus-ring);outline-offset:-2px}.sr-only.sc-rp-recipe-card{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.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%, var(--rp-card-fallback-sheen, rgb(255 255 255 / 0.55)), transparent 55%), linear-gradient( 135deg, var(--rp-card-fallback-from, var(--rp-caramel-100)), var(--rp-card-fallback-to, 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:var(--rp-card-favorite-bg, rgb(255 255 255 / 0.82));backdrop-filter:blur(8px);border:1px solid var(--rp-card-favorite-border, 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-card-favorite-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-strong)}[favorite].sc-rp-recipe-card-h .favorite.sc-rp-recipe-card:hover svg.sc-rp-recipe-card{fill:var(--rp-color-favorite-strong)}.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;flex-wrap:wrap;gap:var(--rp-space-2);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)}}.favorite.is-pulsing.sc-rp-recipe-card svg.sc-rp-recipe-card{animation:rp-heart-beat 400ms var(--rp-ease);transform-origin:center}@keyframes rp-heart-beat{0%{transform:scale(1)}30%{transform:scale(0.7)}55%{transform:scale(1.35)}75%{transform:scale(0.94)}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}}";const d=class{constructor(a){r(this,a),this.rpSearch=e(this,"rpSearch"),this.rpClear=e(this,"rpClear")}value="";placeholder="Search recipes";label="Search recipes";draft="";rpSearch;rpClear;onValueChange(r){this.draft=r??""}componentWillLoad(){this.draft=this.value??""}onSubmit=r=>{r.preventDefault(),this.rpSearch.emit(this.draft.trim())};onInput=r=>{this.draft=r.target.value};onClear=()=>{this.draft="",this.rpClear.emit()};render(){return a(s,{key:"98c0c2367f27c061759b4fcae36b09fb4f88a720"},a("form",{key:"de043755e60e10f39b102605b5347416abf9dc8f",class:"bar",role:"search",onSubmit:this.onSubmit},a("svg",{key:"f5fdf365cd2901deb885068afece74c843a9d174",class:"icon",viewBox:"0 0 24 24",width:"18",height:"18","aria-hidden":"true"},a("circle",{key:"9ad873f8544081cbd16f7666e428565ade2cdbed",cx:"11",cy:"11",r:"7"}),a("path",{key:"d6284fb25056636002e6cde74a1bd7bf36f40291",d:"m20 20-3.6-3.6"})),a("input",{key:"17288bc6a472a736d78d8beef70316547c7eb11f",type:"search",class:"field",value:this.draft,placeholder:this.placeholder,"aria-label":this.label,onInput:this.onInput}),this.draft&&a("button",{key:"468a3c549bad63863a6bce18d0d46335705ace89",type:"button",class:"clear",onClick:this.onClear,"aria-label":"Clear search"},a("svg",{key:"70bab6cfdea49c209208e19a496ab24429bf704e",viewBox:"0 0 24 24",width:"14",height:"14","aria-hidden":"true"},a("path",{key:"dcafa21163e380fed6ff35dff0e8f1915b7d5500",d:"M6 6l12 12M18 6L6 18"}))),a("button",{key:"24ac96852bb46844121597ee647c5e35304b9df9",type:"submit",class:"submit","aria-label":"Search"},a("span",{key:"d6e9577315a844403e120fb705a180f49c8f5733",class:"submit-text"},"Search"),a("svg",{key:"9fa48cfa05c8d8a3b5f328131c12a5b954069e56",class:"submit-icon",viewBox:"0 0 24 24",width:"17",height:"17","aria-hidden":"true"},a("circle",{key:"e9367a2e0ee4e05f3b39cbd728f2ea968a1c129f",cx:"11",cy:"11",r:"7"}),a("path",{key:"f2f41503b77ae140224746a419f792ceb77ea5ff",d:"m20 20-3.6-3.6"})))))}static get watchers(){return{value:[{onValueChange:0}]}}};d.style=".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)}.submit-icon.sc-rp-search-bar{display:none;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}.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: 560px){.bar.sc-rp-search-bar{padding-inline-start:var(--rp-space-3);gap:var(--rp-space-1)}.submit.sc-rp-search-bar{display:grid;place-items:center;width:38px;height:38px;padding:0}.submit-text.sc-rp-search-bar{display:none}.submit-icon.sc-rp-search-bar{display:block}}@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}}";const l=class{constructor(a){r(this,a),this.rpSelectChange=e(this,"rpSelectChange")}get el(){return o(this)}options=[];value="";label="";placeholder="Choose…";open=!1;disabled=!1;compact=!1;dropUp=!1;activeIndex=-1;rpSelectChange;triggerEl;listEl;typeBuffer="";typeTimer;onOpenChange(r){if(!r)return window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0),this.el.style.removeProperty("--rp-select-max-height"),void(this.dropUp=!1);this.activeIndex=Math.max(0,this.normalizedOptions.findIndex((r=>r.value===this.value))),requestAnimationFrame((()=>requestAnimationFrame((()=>{this.position(),this.scrollActiveIntoView()})))),window.addEventListener("resize",this.position),window.addEventListener("scroll",this.onAncestorScroll,!0)}onOptionsChange(){this.open&&requestAnimationFrame((()=>requestAnimationFrame((()=>this.position()))))}disconnectedCallback(){clearTimeout(this.typeTimer),window.removeEventListener("resize",this.position),window.removeEventListener("scroll",this.onAncestorScroll,!0)}onAncestorScroll=r=>{r.target!==this.listEl&&this.position()};position=()=>{if(!this.open||!this.triggerEl)return;const r=this.triggerEl.getBoundingClientRect(),e=this.clippingBounds(),a=Math.min(window.innerHeight,e.bottom),s=Math.max(0,e.top),o=a-r.bottom-8-12,t=r.top-s-8-12,i=o<(this.listEl?Math.min(260,this.listEl.scrollHeight):Math.min(260,40*this.normalizedOptions.length+8))&&t>o;this.dropUp=i;const c=Math.max(96,Math.floor(i?t:o));this.el.style.setProperty("--rp-select-max-height",`${c}px`)};clippingBounds(){let r=this.el.parentElement;for(;r&&r!==document.body;){const e=getComputedStyle(r);if("visible"!==e.overflow&&"visible"!==e.overflowY){const e=r.getBoundingClientRect();if(e.height>0)return{top:e.top,bottom:e.bottom}}r=r.parentElement}return{top:0,bottom:window.innerHeight}}async focusControl(){this.triggerEl?.focus()}onDocumentPointerDown(r){this.open&&(this.el.contains(r.target)||(this.open=!1))}get normalizedOptions(){return Array.isArray(this.options)?this.options:[]}get selectedOption(){return this.normalizedOptions.find((r=>r.value===this.value))}choose(r,e){this.value=r.value,this.open=!1,this.rpSelectChange.emit(r.value),this.triggerEl?.focus(),e&&this.swallowGhostClick(e.x,e.y)}swallowGhostClick(r,e){const a=a=>{Math.hypot(a.clientX-r,a.clientY-e)>24||(a.preventDefault(),a.stopPropagation(),s())},s=()=>{window.clearTimeout(o),document.removeEventListener("click",a,!0)};document.addEventListener("click",a,!0);const o=window.setTimeout(s,500)}scrollActiveIntoView(){const r=this.listEl?.querySelector(".option.is-active");r?.scrollIntoView({block:"nearest"})}move(r){const e=this.normalizedOptions;if(0===e.length)return;const a=this.activeIndex+r;this.activeIndex=a<0?e.length-1:a%e.length,requestAnimationFrame((()=>this.scrollActiveIntoView()))}typeAhead(r){clearTimeout(this.typeTimer),this.typeBuffer+=r.toLowerCase(),this.typeTimer=setTimeout((()=>this.typeBuffer=""),600);const e=this.normalizedOptions.findIndex((r=>r.label.toLowerCase().startsWith(this.typeBuffer)));-1!==e&&(this.open?(this.activeIndex=e,requestAnimationFrame((()=>this.scrollActiveIntoView()))):this.choose(this.normalizedOptions[e]))}onKeyDown=r=>{if(!this.disabled)switch(r.key){case"ArrowDown":return r.preventDefault(),void(this.open?this.move(1):this.open=!0);case"ArrowUp":return r.preventDefault(),void(this.open?this.move(-1):this.open=!0);case"Home":if(!this.open)return;return r.preventDefault(),this.activeIndex=0,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"End":if(!this.open)return;return r.preventDefault(),this.activeIndex=this.normalizedOptions.length-1,void requestAnimationFrame((()=>this.scrollActiveIntoView()));case"Enter":case" ":return r.preventDefault(),void(this.open?this.activeIndex>=0&&this.choose(this.normalizedOptions[this.activeIndex]):this.open=!0);case"Escape":if(!this.open)return;return r.preventDefault(),void(this.open=!1);case"Tab":return void(this.open=!1);default:1!==r.key.length||r.metaKey||r.ctrlKey||r.altKey||(r.preventDefault(),this.typeAhead(r.key))}};render(){const r=this.normalizedOptions,e=this.selectedOption,o="rp-select-list";return a(s,{key:"ebc4162f0e81b6d0ff79fd9a0967030ffa01c483"},a("div",{key:"99ff2315652ccec4f747280754367818ad5a7bae",class:"wrap"},a("button",{key:"3464c691b00cb4e0b4ffed094209d103cd4ccd36",type:"button",class:"trigger",ref:r=>this.triggerEl=r,disabled:this.disabled,role:"combobox","aria-expanded":this.open?"true":"false","aria-controls":o,"aria-haspopup":"listbox","aria-label":this.label||void 0,"aria-activedescendant":this.open&&this.activeIndex>=0?`rp-select-option-${this.activeIndex}`:void 0,onKeyDown:this.onKeyDown,onPointerDown:r=>{this.disabled||(r.preventDefault(),this.triggerEl?.focus(),this.open=!this.open)}},a("span",{key:"169714fb00d19f3ab58822d113fb994424995e90",class:{"trigger-value":!0,"is-placeholder":!e}},e?.label??this.placeholder),a("svg",{key:"002c4c2783d9f1bc2a3802404e7d16025478f65d",class:"chevron",viewBox:"0 0 24 24",width:"14",height:"14","aria-hidden":"true"},a("path",{key:"b5970c61cc218dda77e7cbfebee34e533e76bae2",d:"m6 9 6 6 6-6"}))),this.open&&a("div",{key:"26a3d38fcb704ee018e90fae2601539e04a8fa07",class:"list",id:o,role:"listbox",tabindex:-1,"aria-label":this.label||void 0,ref:r=>this.listEl=r},0===r.length?a("p",{class:"empty"},"No options"):r.map(((r,e)=>a("button",{key:r.value,id:`rp-select-option-${e}`,type:"button",role:"option","aria-selected":r.value===this.value?"true":"false",class:{option:!0,"is-selected":r.value===this.value,"is-active":e===this.activeIndex},onPointerDown:e=>{e.preventDefault(),this.choose(r,"mouse"===e.pointerType?void 0:{x:e.clientX,y:e.clientY})},onMouseEnter:()=>this.activeIndex=e},a("span",{class:"option-text"},r.label),r.value===this.value&&a("svg",{viewBox:"0 0 24 24",width:"15",height:"15","aria-hidden":"true"},a("path",{d:"m5 13 4 4L19 7"}))))))))}static get watchers(){return{open:[{onOpenChange:0}],options:[{onOptionsChange:0}]}}};l.style=".sc-rp-select-h{display:block;font-family:var(--rp-font-sans)}.wrap.sc-rp-select{position:relative}.trigger.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:11px var(--rp-space-4);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;color:var(--rp-color-text);text-align:start;cursor:pointer;background:var(--rp-color-surface);border:1px solid var(--rp-color-border-strong);border-radius:var(--rp-radius-md);transition:border-color var(--rp-duration-fast) var(--rp-ease), box-shadow var(--rp-duration-fast) var(--rp-ease)}.trigger.sc-rp-select:hover:not(:disabled){border-color:var(--rp-color-text-subtle)}.trigger.sc-rp-select:focus-visible,[open].sc-rp-select-h .trigger.sc-rp-select{outline:none;border-color:var(--rp-color-focus);box-shadow:var(--rp-focus-halo)}.trigger.sc-rp-select:disabled{cursor:not-allowed;opacity:0.55}.trigger-value.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.trigger-value.is-placeholder.sc-rp-select{color:var(--rp-color-text-subtle)}.chevron.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-text-muted);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--rp-duration-fast) var(--rp-ease)}[open].sc-rp-select-h .chevron.sc-rp-select{transform:rotate(180deg)}.list.sc-rp-select{position:absolute;inset-block-start:calc(100% + var(--rp-space-1));inset-inline:0;z-index:40;max-height:min(260px, var(--rp-select-max-height, 260px));padding:var(--rp-space-1);overflow-y:auto;overscroll-behavior:contain;background:var(--rp-color-surface);border:1px solid var(--rp-color-border);border-radius:var(--rp-radius-lg);box-shadow:var(--rp-shadow-lg)}[drop-up].sc-rp-select-h .list.sc-rp-select{inset-block-start:auto;inset-block-end:calc(100% + var(--rp-space-1))}.option.sc-rp-select{display:flex;gap:var(--rp-space-2);align-items:center;justify-content:space-between;width:100%;padding:9px var(--rp-space-3);font-family:var(--rp-font-sans);font-size:var(--rp-font-size-md);font-weight:500;letter-spacing:-0.005em;line-height:1.4;color:var(--rp-color-text-body);text-align:start;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)}.option-text.sc-rp-select{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.option.sc-rp-select svg.sc-rp-select{flex-shrink:0;fill:none;stroke:var(--rp-color-highlight);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}.option.is-active.sc-rp-select{color:var(--rp-color-text);background:var(--rp-color-surface-sunken)}.option.is-selected.sc-rp-select{font-weight:600;color:var(--rp-color-text)}.empty.sc-rp-select{margin:0;padding:var(--rp-space-4) var(--rp-space-3);font-size:var(--rp-font-size-sm);font-weight:500;color:var(--rp-color-text-subtle);text-align:center}[compact].sc-rp-select-h .trigger.sc-rp-select{padding:4px var(--rp-space-2);font-size:var(--rp-font-size-xs);color:var(--rp-color-text-muted);border-color:var(--rp-color-border);border-radius:var(--rp-radius-sm)}[compact].sc-rp-select-h .list.sc-rp-select{min-width:148px}[compact].sc-rp-select-h .option.sc-rp-select{padding:7px var(--rp-space-3);font-size:var(--rp-font-size-sm)}@media (prefers-reduced-motion: no-preference){.list.sc-rp-select{animation:rp-select-in var(--rp-duration-fast) var(--rp-ease);transform-origin:top}@keyframes rp-select-in{from{opacity:0;transform:translateY(-4px) scale(0.99)}}}@media (prefers-reduced-motion: reduce){.trigger.sc-rp-select,.chevron.sc-rp-select,.option.sc-rp-select{transition:none}}";export{t as rp_filter_chips,i as rp_ingredient_list,n as rp_modal,p as rp_recipe_card,d as rp_search_bar,l as rp_select}