@ssejal8/recipe-ui-kit 0.1.0 → 0.1.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.
Files changed (191) hide show
  1. package/README.md +108 -277
  2. package/dist/cjs/index-BEr8BsSA.js +1712 -0
  3. package/dist/cjs/index-BEr8BsSA.js.map +1 -0
  4. package/dist/cjs/index.cjs.js +5 -0
  5. package/dist/cjs/index.cjs.js.map +1 -0
  6. package/dist/cjs/loader.cjs.js +15 -0
  7. package/dist/cjs/loader.cjs.js.map +1 -0
  8. package/dist/cjs/recipe-kit.cjs.js +27 -0
  9. package/dist/cjs/recipe-kit.cjs.js.map +1 -0
  10. package/dist/cjs/rk-badge_10.cjs.entry.js +638 -0
  11. package/dist/cjs/rk-badge_10.cjs.entry.js.map +1 -0
  12. package/dist/collection/collection-manifest.json +22 -0
  13. package/dist/collection/components/rk-badge/rk-badge.js +97 -0
  14. package/dist/collection/components/rk-badge/rk-badge.js.map +1 -0
  15. package/dist/collection/components/rk-chip/rk-chip.js +245 -0
  16. package/dist/collection/components/rk-chip/rk-chip.js.map +1 -0
  17. package/dist/collection/components/rk-empty-state/rk-empty-state.js +138 -0
  18. package/dist/collection/components/rk-empty-state/rk-empty-state.js.map +1 -0
  19. package/dist/collection/components/rk-meal-slot/rk-meal-slot.js +312 -0
  20. package/dist/collection/components/rk-meal-slot/rk-meal-slot.js.map +1 -0
  21. package/dist/collection/components/rk-modal/rk-modal.js +256 -0
  22. package/dist/collection/components/rk-modal/rk-modal.js.map +1 -0
  23. package/dist/collection/components/rk-rating/rk-rating.js +228 -0
  24. package/dist/collection/components/rk-rating/rk-rating.js.map +1 -0
  25. package/dist/collection/components/rk-recipe-card/rk-recipe-card.js +366 -0
  26. package/dist/collection/components/rk-recipe-card/rk-recipe-card.js.map +1 -0
  27. package/dist/collection/components/rk-search-bar/rk-search-bar.js +291 -0
  28. package/dist/collection/components/rk-search-bar/rk-search-bar.js.map +1 -0
  29. package/dist/collection/components/rk-segmented-control/rk-segmented-control.js +196 -0
  30. package/dist/collection/components/rk-segmented-control/rk-segmented-control.js.map +1 -0
  31. package/dist/collection/components/rk-tag-input/rk-tag-input.js +264 -0
  32. package/dist/collection/components/rk-tag-input/rk-tag-input.js.map +1 -0
  33. package/dist/collection/index.js +2 -0
  34. package/dist/collection/index.js.map +1 -0
  35. package/dist/components/index.d.ts +35 -0
  36. package/dist/components/index.js +2 -0
  37. package/dist/components/index.js.map +1 -0
  38. package/dist/components/rk-badge.d.ts +11 -0
  39. package/dist/components/rk-badge.js +2 -0
  40. package/dist/components/rk-badge.js.map +1 -0
  41. package/dist/components/rk-chip.d.ts +11 -0
  42. package/dist/components/rk-chip.js +2 -0
  43. package/dist/components/rk-chip.js.map +1 -0
  44. package/dist/components/rk-empty-state.d.ts +11 -0
  45. package/dist/components/rk-empty-state.js +2 -0
  46. package/dist/components/rk-empty-state.js.map +1 -0
  47. package/dist/components/rk-meal-slot.d.ts +11 -0
  48. package/dist/components/rk-meal-slot.js +2 -0
  49. package/dist/components/rk-meal-slot.js.map +1 -0
  50. package/dist/components/rk-modal.d.ts +11 -0
  51. package/dist/components/rk-modal.js +2 -0
  52. package/dist/components/rk-modal.js.map +1 -0
  53. package/dist/components/rk-rating.d.ts +11 -0
  54. package/dist/components/rk-rating.js +2 -0
  55. package/dist/components/rk-rating.js.map +1 -0
  56. package/dist/components/rk-recipe-card.d.ts +11 -0
  57. package/dist/components/rk-recipe-card.js +2 -0
  58. package/dist/components/rk-recipe-card.js.map +1 -0
  59. package/dist/components/rk-search-bar.d.ts +11 -0
  60. package/dist/components/rk-search-bar.js +2 -0
  61. package/dist/components/rk-search-bar.js.map +1 -0
  62. package/dist/components/rk-segmented-control.d.ts +11 -0
  63. package/dist/components/rk-segmented-control.js +2 -0
  64. package/dist/components/rk-segmented-control.js.map +1 -0
  65. package/dist/components/rk-tag-input.d.ts +11 -0
  66. package/dist/components/rk-tag-input.js +2 -0
  67. package/dist/components/rk-tag-input.js.map +1 -0
  68. package/dist/esm/index-Bxo0C8lB.js +1684 -0
  69. package/dist/esm/index-Bxo0C8lB.js.map +1 -0
  70. package/dist/esm/index.js +4 -0
  71. package/dist/esm/index.js.map +1 -0
  72. package/dist/esm/loader.js +13 -0
  73. package/dist/esm/loader.js.map +1 -0
  74. package/dist/esm/recipe-kit.js +23 -0
  75. package/dist/esm/recipe-kit.js.map +1 -0
  76. package/dist/esm/rk-badge_10.entry.js +627 -0
  77. package/dist/esm/rk-badge_10.entry.js.map +1 -0
  78. package/dist/index.cjs.js +1 -0
  79. package/dist/index.js +1 -0
  80. package/dist/recipe-kit/index.esm.js +2 -0
  81. package/dist/recipe-kit/index.esm.js.map +1 -0
  82. package/dist/recipe-kit/p-Bxo0C8lB.js +3 -0
  83. package/dist/recipe-kit/p-Bxo0C8lB.js.map +1 -0
  84. package/dist/recipe-kit/p-fcb955c7.entry.js +2 -0
  85. package/dist/recipe-kit/p-fcb955c7.entry.js.map +1 -0
  86. package/dist/recipe-kit/recipe-kit.css +1 -0
  87. package/dist/recipe-kit/recipe-kit.esm.js +2 -0
  88. package/dist/recipe-kit/recipe-kit.esm.js.map +1 -0
  89. package/dist/recipe-kit/rk-global.css +104 -0
  90. package/dist/types/components/rk-badge/rk-badge.d.ts +15 -0
  91. package/dist/types/components/rk-chip/rk-chip.d.ts +37 -0
  92. package/dist/types/components/rk-empty-state/rk-empty-state.d.ts +19 -0
  93. package/dist/types/components/rk-meal-slot/rk-meal-slot.d.ts +53 -0
  94. package/dist/types/components/rk-modal/rk-modal.d.ts +41 -0
  95. package/dist/types/components/rk-rating/rk-rating.d.ts +26 -0
  96. package/dist/types/components/rk-recipe-card/rk-recipe-card.d.ts +67 -0
  97. package/dist/types/components/rk-search-bar/rk-search-bar.d.ts +39 -0
  98. package/dist/types/components/rk-segmented-control/rk-segmented-control.d.ts +37 -0
  99. package/dist/types/components/rk-tag-input/rk-tag-input.d.ts +35 -0
  100. package/{packages/recipe-kit-stencil/src → dist/types}/components.d.ts +1 -1
  101. package/{packages/recipe-kit-stencil/src/index.ts → dist/types/index.d.ts} +0 -2
  102. package/dist/types/stencil-public-runtime.d.ts +1873 -0
  103. package/loader/cdn.js +1 -0
  104. package/loader/index.cjs.js +1 -0
  105. package/loader/index.d.ts +24 -0
  106. package/loader/index.es2017.js +1 -0
  107. package/loader/index.js +2 -0
  108. package/package.json +84 -22
  109. package/.claude/settings.local.json +0 -10
  110. package/.npmr +0 -1
  111. package/apps/recipe-web/package.json +0 -31
  112. package/apps/recipe-web/src/app.css +0 -418
  113. package/apps/recipe-web/src/app.d.ts +0 -32
  114. package/apps/recipe-web/src/app.html +0 -25
  115. package/apps/recipe-web/src/lib/api/mealdb.ts +0 -240
  116. package/apps/recipe-web/src/lib/components/AppHeader.svelte +0 -290
  117. package/apps/recipe-web/src/lib/components/ConfirmDialog.svelte +0 -46
  118. package/apps/recipe-web/src/lib/components/Modal.svelte +0 -33
  119. package/apps/recipe-web/src/lib/components/RecipeCard.svelte +0 -100
  120. package/apps/recipe-web/src/lib/components/RecipeForm.svelte +0 -560
  121. package/apps/recipe-web/src/lib/components/RecipeGrid.svelte +0 -77
  122. package/apps/recipe-web/src/lib/components/RecipePickerDialog.svelte +0 -185
  123. package/apps/recipe-web/src/lib/components/Toaster.svelte +0 -111
  124. package/apps/recipe-web/src/lib/domain/recipe.ts +0 -130
  125. package/apps/recipe-web/src/lib/domain/validation.ts +0 -189
  126. package/apps/recipe-web/src/lib/stencil/WebComponent.svelte +0 -145
  127. package/apps/recipe-web/src/lib/stencil/register.ts +0 -28
  128. package/apps/recipe-web/src/lib/stores/favorites.svelte.ts +0 -81
  129. package/apps/recipe-web/src/lib/stores/myRecipes.svelte.ts +0 -98
  130. package/apps/recipe-web/src/lib/stores/persisted.svelte.ts +0 -73
  131. package/apps/recipe-web/src/lib/stores/planner.svelte.ts +0 -275
  132. package/apps/recipe-web/src/lib/stores/theme.svelte.ts +0 -67
  133. package/apps/recipe-web/src/lib/stores/toast.svelte.ts +0 -66
  134. package/apps/recipe-web/src/routes/+error.svelte +0 -36
  135. package/apps/recipe-web/src/routes/+layout.svelte +0 -62
  136. package/apps/recipe-web/src/routes/+page.svelte +0 -352
  137. package/apps/recipe-web/src/routes/+page.ts +0 -107
  138. package/apps/recipe-web/src/routes/favorites/+page.svelte +0 -170
  139. package/apps/recipe-web/src/routes/my-recipes/+layout.ts +0 -55
  140. package/apps/recipe-web/src/routes/my-recipes/+page.svelte +0 -180
  141. package/apps/recipe-web/src/routes/my-recipes/[id]/edit/+page.svelte +0 -104
  142. package/apps/recipe-web/src/routes/my-recipes/new/+page.svelte +0 -67
  143. package/apps/recipe-web/src/routes/planner/+page.svelte +0 -422
  144. package/apps/recipe-web/src/routes/recipes/[id]/+page.svelte +0 -538
  145. package/apps/recipe-web/src/routes/recipes/[id]/+page.ts +0 -24
  146. package/apps/recipe-web/static/favicon.svg +0 -8
  147. package/apps/recipe-web/static/robots.txt +0 -2
  148. package/apps/recipe-web/svelte.config.js +0 -35
  149. package/apps/recipe-web/tsconfig.json +0 -14
  150. package/apps/recipe-web/vite.config.ts +0 -23
  151. package/packages/recipe-kit-stencil/README.md +0 -185
  152. package/packages/recipe-kit-stencil/package-lock.json +0 -4772
  153. package/packages/recipe-kit-stencil/package.json +0 -91
  154. package/packages/recipe-kit-stencil/src/components/rk-badge/readme.md +0 -38
  155. package/packages/recipe-kit-stencil/src/components/rk-badge/rk-badge.tsx +0 -31
  156. package/packages/recipe-kit-stencil/src/components/rk-chip/readme.md +0 -52
  157. package/packages/recipe-kit-stencil/src/components/rk-chip/rk-chip.tsx +0 -105
  158. package/packages/recipe-kit-stencil/src/components/rk-empty-state/readme.md +0 -44
  159. package/packages/recipe-kit-stencil/src/components/rk-empty-state/rk-empty-state.tsx +0 -50
  160. package/packages/recipe-kit-stencil/src/components/rk-meal-slot/readme.md +0 -58
  161. package/packages/recipe-kit-stencil/src/components/rk-meal-slot/rk-meal-slot.tsx +0 -182
  162. package/packages/recipe-kit-stencil/src/components/rk-modal/readme.md +0 -57
  163. package/packages/recipe-kit-stencil/src/components/rk-modal/rk-modal.tsx +0 -176
  164. package/packages/recipe-kit-stencil/src/components/rk-rating/readme.md +0 -42
  165. package/packages/recipe-kit-stencil/src/components/rk-rating/rk-rating.tsx +0 -114
  166. package/packages/recipe-kit-stencil/src/components/rk-recipe-card/readme.md +0 -66
  167. package/packages/recipe-kit-stencil/src/components/rk-recipe-card/rk-recipe-card.tsx +0 -179
  168. package/packages/recipe-kit-stencil/src/components/rk-recipe-card/test/rk-recipe-card.spec.tsx +0 -70
  169. package/packages/recipe-kit-stencil/src/components/rk-search-bar/readme.md +0 -67
  170. package/packages/recipe-kit-stencil/src/components/rk-search-bar/rk-search-bar.tsx +0 -152
  171. package/packages/recipe-kit-stencil/src/components/rk-search-bar/test/rk-search-bar.spec.tsx +0 -93
  172. package/packages/recipe-kit-stencil/src/components/rk-segmented-control/readme.md +0 -41
  173. package/packages/recipe-kit-stencil/src/components/rk-segmented-control/rk-segmented-control.tsx +0 -115
  174. package/packages/recipe-kit-stencil/src/components/rk-tag-input/readme.md +0 -47
  175. package/packages/recipe-kit-stencil/src/components/rk-tag-input/rk-tag-input.tsx +0 -181
  176. package/packages/recipe-kit-stencil/src/components/rk-tag-input/test/rk-tag-input.spec.tsx +0 -76
  177. package/packages/recipe-kit-stencil/src/index.html +0 -259
  178. package/packages/recipe-kit-stencil/stencil.config.ts +0 -41
  179. package/packages/recipe-kit-stencil/tsconfig.json +0 -24
  180. /package/{packages/recipe-kit-stencil/LICENSE → LICENSE} +0 -0
  181. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-badge/rk-badge.css +0 -0
  182. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-chip/rk-chip.css +0 -0
  183. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-empty-state/rk-empty-state.css +0 -0
  184. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-meal-slot/rk-meal-slot.css +0 -0
  185. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-modal/rk-modal.css +0 -0
  186. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-rating/rk-rating.css +0 -0
  187. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-recipe-card/rk-recipe-card.css +0 -0
  188. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-search-bar/rk-search-bar.css +0 -0
  189. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-segmented-control/rk-segmented-control.css +0 -0
  190. /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-tag-input/rk-tag-input.css +0 -0
  191. /package/{packages/recipe-kit-stencil/src/global → dist/collection}/rk-global.css +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkBadgeCss","RkBadge","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","tone","variant","small","render","h","key","class","badge","part"],"sources":["src/components/rk-badge/rk-badge.css?tag=rk-badge&encapsulation=shadow","src/components/rk-badge/rk-badge.tsx"],"sourcesContent":[":host {\n display: inline-flex;\n font-family: var(--rk-font);\n vertical-align: middle;\n}\n\n.badge {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n border-radius: var(--rk-radius-pill, 999px);\n border: 1px solid transparent;\n font-size: 0.76em;\n font-weight: 650;\n line-height: 1.35;\n letter-spacing: 0.01em;\n white-space: nowrap;\n}\n\n.badge.is-small {\n padding: 2px 8px;\n font-size: 0.7em;\n}\n\n/* --- soft (default) --- */\n.variant-soft.tone-neutral {\n background: var(--rk-surface-2, #fdf5ef);\n color: var(--rk-ink-2, #52443c);\n}\n.variant-soft.tone-primary {\n background: var(--rk-primary-soft, #fdeee6);\n color: var(--rk-primary-strong, #b23c11);\n}\n.variant-soft.tone-accent {\n background: var(--rk-accent-soft, #e2f3f1);\n color: var(--rk-accent, #0f766e);\n}\n.variant-soft.tone-success {\n background: var(--rk-success-soft, #e6f5eb);\n color: var(--rk-success, #15803d);\n}\n.variant-soft.tone-warning {\n background: var(--rk-warning-soft, #fdf3d8);\n color: var(--rk-warning, #a16207);\n}\n.variant-soft.tone-danger {\n background: var(--rk-danger-soft, #fdeae1);\n color: var(--rk-danger, #c2410c);\n}\n\n/* --- solid --- */\n.variant-solid {\n color: #fff;\n}\n.variant-solid.tone-neutral {\n background: var(--rk-ink, #211a16);\n}\n.variant-solid.tone-primary {\n background: var(--rk-primary, #d94f1b);\n}\n.variant-solid.tone-accent {\n background: var(--rk-accent, #0f766e);\n}\n.variant-solid.tone-success {\n background: var(--rk-success, #15803d);\n}\n.variant-solid.tone-warning {\n background: var(--rk-warning, #a16207);\n}\n.variant-solid.tone-danger {\n background: var(--rk-danger, #c2410c);\n}\n\n/* --- outline --- */\n.variant-outline {\n background: transparent;\n}\n.variant-outline.tone-neutral {\n border-color: var(--rk-border-strong, #d9c6b8);\n color: var(--rk-ink-2, #52443c);\n}\n.variant-outline.tone-primary {\n border-color: var(--rk-primary, #d94f1b);\n color: var(--rk-primary, #d94f1b);\n}\n.variant-outline.tone-accent {\n border-color: var(--rk-accent, #0f766e);\n color: var(--rk-accent, #0f766e);\n}\n.variant-outline.tone-success {\n border-color: var(--rk-success, #15803d);\n color: var(--rk-success, #15803d);\n}\n.variant-outline.tone-warning {\n border-color: var(--rk-warning, #a16207);\n color: var(--rk-warning, #a16207);\n}\n.variant-outline.tone-danger {\n border-color: var(--rk-danger, #c2410c);\n color: var(--rk-danger, #c2410c);\n}\n","import { Component, h, Prop } from '@stencil/core';\n\n/**\n * A small, non-interactive label. Purely slot-driven so hosts can put icons,\n * text or counts inside it.\n *\n * @slot - Badge content.\n */\n@Component({\n tag: 'rk-badge',\n styleUrl: 'rk-badge.css',\n shadow: true,\n})\nexport class RkBadge {\n /** Color treatment. */\n @Prop() tone: 'neutral' | 'primary' | 'accent' | 'success' | 'warning' | 'danger' = 'neutral';\n\n /** `soft` is tinted, `solid` is filled, `outline` is bordered only. */\n @Prop() variant: 'soft' | 'solid' | 'outline' = 'soft';\n\n /** Compact sizing for dense layouts. */\n @Prop() small = false;\n\n render() {\n return (\n <span class={{ badge: true, [`tone-${this.tone}`]: true, [`variant-${this.variant}`]: true, 'is-small': this.small }} part=\"badge\">\n <slot />\n </span>\n );\n }\n}\n"],"mappings":"oDAAA,MAAMA,EAAa,IAAM,4/D,MCaZC,EAAOC,EAAA,MAAAD,UAAAE,EALpB,WAAAC,CAAAC,G,kEAOUC,KAAAC,KAA4E,UAG5ED,KAAAE,QAAwC,OAGxCF,KAAAG,MAAQ,KASjB,CAPC,MAAAC,GACE,OACEC,EAAA,QAAAC,IAAA,2CAAMC,MAAO,CAAEC,MAAO,KAAM,CAAC,QAAQR,KAAKC,QAAS,KAAM,CAAC,WAAWD,KAAKE,WAAY,KAAM,WAAYF,KAAKG,OAASM,KAAK,SACzHJ,EAAA,QAAAC,IAAA,6C","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkChip extends Components.RkChip, HTMLElement {}
4
+ export const RkChip: {
5
+ prototype: RkChip;
6
+ new (): RkChip;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as r,H as i,c as s,h as e,t}from"./index.js";const o=()=>`:host{display:inline-flex;font-family:var(--rk-font);vertical-align:middle}.chip,.body{display:inline-flex;align-items:center;gap:7px;font:inherit;font-size:0.88em;font-weight:550;line-height:1;color:var(--rk-ink-2, #52443c);background:var(--rk-surface, #fff);border:1px solid var(--rk-border, #ecdfd4);border-radius:var(--rk-radius-pill, 999px);padding:9px 15px;cursor:pointer;white-space:nowrap;transition:background var(--rk-transition), border-color var(--rk-transition), color var(--rk-transition), transform var(--rk-transition)}.chip:hover:not(:disabled),.body:hover:not(:disabled){border-color:var(--rk-border-strong, #d9c6b8);background:var(--rk-surface-2, #fdf5ef)}.chip:active:not(:disabled){transform:translateY(1px)}.chip:focus-visible,.body:focus-visible,.dismiss:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.chip:disabled,.body:disabled{opacity:0.5;cursor:not-allowed}.chip.is-selected.tone-neutral{background:var(--rk-ink, #211a16);border-color:var(--rk-ink, #211a16);color:var(--rk-surface, #fff)}.chip.is-selected.tone-primary{background:var(--rk-primary, #d94f1b);border-color:var(--rk-primary, #d94f1b);color:#fff}.chip.is-selected.tone-accent{background:var(--rk-accent, #0f766e);border-color:var(--rk-accent, #0f766e);color:#fff}.chip.is-selected:hover:not(:disabled){filter:brightness(1.08)}.count{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:var(--rk-radius-pill, 999px);background:var(--rk-surface-2, #fdf5ef);color:var(--rk-muted, #857166);font-size:0.78em;font-weight:650}.chip.is-selected .count{background:rgba(255, 255, 255, 0.22);color:inherit}.lead{display:contents}.lead ::slotted(*){font-size:1.05em;line-height:1}.chip.is-dismissible{padding:0;background:transparent;border:0;border-radius:var(--rk-radius-pill, 999px);gap:0}.chip.is-dismissible .body{border-top-right-radius:0;border-bottom-right-radius:0;border-right:0}.dismiss{display:inline-flex;align-items:center;justify-content:center;width:32px;padding:0;border:1px solid var(--rk-border, #ecdfd4);border-left:0;border-radius:0 var(--rk-radius-pill, 999px) var(--rk-radius-pill, 999px) 0;background:var(--rk-surface, #fff);color:var(--rk-muted, #857166);cursor:pointer;transition:background var(--rk-transition), color var(--rk-transition)}.dismiss:hover:not(:disabled){background:var(--rk-danger-soft, #fdeae1);color:var(--rk-danger, #c2410c)}.dismiss:disabled{opacity:0.5;cursor:not-allowed}.dismiss svg{width:12px;height:12px}@media (prefers-reduced-motion: reduce){.chip,.body,.dismiss{transition:none}}`;const a=r(class r extends i{constructor(r){super();if(r!==false){this.__registerHost()}this.__attachShadow();this.rkChipToggle=s(this,"rkChipToggle");this.rkChipDismiss=s(this,"rkChipDismiss");this.label="";this.selected=false;this.dismissible=false;this.disabled=false;this.tone="neutral";this.handleClick=()=>{if(this.disabled)return;this.rkChipToggle.emit({value:this.resolvedValue,label:this.label,selected:!this.selected})};this.handleDismiss=r=>{r.stopPropagation();if(this.disabled)return;this.rkChipDismiss.emit({value:this.resolvedValue,label:this.label})}}get resolvedValue(){return this.value??this.label}render(){const r=[e("span",{class:"lead"},e("slot",null)),e("span",{class:"label",part:"label"},this.label),typeof this.count==="number"&&e("span",{class:"count",part:"count"},this.count)];const i={chip:true,"is-selected":this.selected,"is-dismissible":this.dismissible,[`tone-${this.tone}`]:true};if(this.dismissible){return e("span",{class:i,part:"chip"},e("button",{class:"body",type:"button",disabled:this.disabled,onClick:this.handleClick},r),e("button",{class:"dismiss",part:"dismiss",type:"button",disabled:this.disabled,"aria-label":`Remove ${this.label}`,onClick:this.handleDismiss},e("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.4","stroke-linecap":"round","aria-hidden":"true"},e("path",{d:"M6 6l12 12M18 6 6 18"}))))}return e("button",{class:i,part:"chip",type:"button","aria-pressed":String(this.selected),disabled:this.disabled,onClick:this.handleClick},r)}static get style(){return o()}},[257,"rk-chip",{label:[1],value:[1],selected:[4],count:[2],dismissible:[4],disabled:[4],tone:[1]}]);function n(){if(typeof customElements==="undefined"){return}const r=["rk-chip"];r.forEach((r=>{switch(r){case"rk-chip":if(!customElements.get(t(r))){customElements.define(t(r),a)}break}}))}n();const d=a;const l=n;export{d as RkChip,l as defineCustomElement};
2
+ //# sourceMappingURL=rk-chip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkChipCss","RkChip","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","label","selected","dismissible","disabled","tone","handleClick","rkChipToggle","emit","value","resolvedValue","handleDismiss","event","stopPropagation","rkChipDismiss","render","body","h","class","part","count","classes","chip","type","onClick","viewBox","fill","stroke","d","String"],"sources":["src/components/rk-chip/rk-chip.css?tag=rk-chip&encapsulation=shadow","src/components/rk-chip/rk-chip.tsx"],"sourcesContent":[":host {\n display: inline-flex;\n font-family: var(--rk-font);\n vertical-align: middle;\n}\n\n.chip,\n.body {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font: inherit;\n font-size: 0.88em;\n font-weight: 550;\n line-height: 1;\n color: var(--rk-ink-2, #52443c);\n background: var(--rk-surface, #fff);\n border: 1px solid var(--rk-border, #ecdfd4);\n border-radius: var(--rk-radius-pill, 999px);\n padding: 9px 15px;\n cursor: pointer;\n white-space: nowrap;\n transition: background var(--rk-transition), border-color var(--rk-transition), color var(--rk-transition), transform var(--rk-transition);\n}\n\n.chip:hover:not(:disabled),\n.body:hover:not(:disabled) {\n border-color: var(--rk-border-strong, #d9c6b8);\n background: var(--rk-surface-2, #fdf5ef);\n}\n\n.chip:active:not(:disabled) {\n transform: translateY(1px);\n}\n\n.chip:focus-visible,\n.body:focus-visible,\n.dismiss:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.chip:disabled,\n.body:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Selected states, per tone */\n.chip.is-selected.tone-neutral {\n background: var(--rk-ink, #211a16);\n border-color: var(--rk-ink, #211a16);\n color: var(--rk-surface, #fff);\n}\n\n.chip.is-selected.tone-primary {\n background: var(--rk-primary, #d94f1b);\n border-color: var(--rk-primary, #d94f1b);\n color: #fff;\n}\n\n.chip.is-selected.tone-accent {\n background: var(--rk-accent, #0f766e);\n border-color: var(--rk-accent, #0f766e);\n color: #fff;\n}\n\n.chip.is-selected:hover:not(:disabled) {\n filter: brightness(1.08);\n}\n\n.count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: var(--rk-radius-pill, 999px);\n background: var(--rk-surface-2, #fdf5ef);\n color: var(--rk-muted, #857166);\n font-size: 0.78em;\n font-weight: 650;\n}\n\n.chip.is-selected .count {\n background: rgba(255, 255, 255, 0.22);\n color: inherit;\n}\n\n/*\n * `display: contents` lets slotted nodes become direct flex items of the chip,\n * so an *empty* leading slot contributes no box and therefore no stray gap.\n */\n.lead {\n display: contents;\n}\n\n.lead ::slotted(*) {\n font-size: 1.05em;\n line-height: 1;\n}\n\n/* Dismissible layout: shell holds two buttons that read as one pill. */\n.chip.is-dismissible {\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: var(--rk-radius-pill, 999px);\n gap: 0;\n}\n\n.chip.is-dismissible .body {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n border-right: 0;\n}\n\n.dismiss {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n padding: 0;\n border: 1px solid var(--rk-border, #ecdfd4);\n border-left: 0;\n border-radius: 0 var(--rk-radius-pill, 999px) var(--rk-radius-pill, 999px) 0;\n background: var(--rk-surface, #fff);\n color: var(--rk-muted, #857166);\n cursor: pointer;\n transition: background var(--rk-transition), color var(--rk-transition);\n}\n\n.dismiss:hover:not(:disabled) {\n background: var(--rk-danger-soft, #fdeae1);\n color: var(--rk-danger, #c2410c);\n}\n\n.dismiss:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.dismiss svg {\n width: 12px;\n height: 12px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .chip,\n .body,\n .dismiss {\n transition: none;\n }\n}\n","import { Component, Event, EventEmitter, h, Prop } from '@stencil/core';\n\n/**\n * A selectable / dismissible filter chip.\n *\n * @slot - Optional leading content (icon, emoji, avatar) rendered before the label.\n */\n@Component({\n tag: 'rk-chip',\n styleUrl: 'rk-chip.css',\n shadow: true,\n})\nexport class RkChip {\n /** Visible text. */\n @Prop() label = '';\n\n /** Value reported back to the host application in event payloads. */\n @Prop() value?: string;\n\n /** Whether the chip is currently active. */\n @Prop() selected = false;\n\n /** Optional trailing count badge (e.g. number of matching recipes). */\n @Prop() count?: number;\n\n /** Renders an \"x\" button that emits `rkChipDismiss` instead of toggling. */\n @Prop() dismissible = false;\n\n /** Disables interaction. */\n @Prop() disabled = false;\n\n /** Visual treatment. */\n @Prop() tone: 'neutral' | 'primary' | 'accent' = 'neutral';\n\n /** Emitted when the chip is toggled. */\n @Event({ eventName: 'rkChipToggle' }) rkChipToggle!: EventEmitter<{ value: string; label: string; selected: boolean }>;\n\n /** Emitted when a dismissible chip's remove button is pressed. */\n @Event({ eventName: 'rkChipDismiss' }) rkChipDismiss!: EventEmitter<{ value: string; label: string }>;\n\n private get resolvedValue() {\n return this.value ?? this.label;\n }\n\n private handleClick = () => {\n if (this.disabled) return;\n this.rkChipToggle.emit({\n value: this.resolvedValue,\n label: this.label,\n selected: !this.selected,\n });\n };\n\n private handleDismiss = (event: MouseEvent) => {\n event.stopPropagation();\n if (this.disabled) return;\n this.rkChipDismiss.emit({ value: this.resolvedValue, label: this.label });\n };\n\n render() {\n const body = [\n <span class=\"lead\">\n <slot />\n </span>,\n <span class=\"label\" part=\"label\">\n {this.label}\n </span>,\n typeof this.count === 'number' && (\n <span class=\"count\" part=\"count\">\n {this.count}\n </span>\n ),\n ];\n\n const classes = {\n chip: true,\n 'is-selected': this.selected,\n 'is-dismissible': this.dismissible,\n [`tone-${this.tone}`]: true,\n };\n\n // A dismissible chip needs two independent controls, so the shell becomes a\n // plain element to avoid nesting buttons inside a button.\n if (this.dismissible) {\n return (\n <span class={classes} part=\"chip\">\n <button class=\"body\" type=\"button\" disabled={this.disabled} onClick={this.handleClick}>\n {body}\n </button>\n <button class=\"dismiss\" part=\"dismiss\" type=\"button\" disabled={this.disabled} aria-label={`Remove ${this.label}`} onClick={this.handleDismiss}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6 6 18\" />\n </svg>\n </button>\n </span>\n );\n }\n\n return (\n <button class={classes} part=\"chip\" type=\"button\" aria-pressed={String(this.selected)} disabled={this.disabled} onClick={this.handleClick}>\n {body}\n </button>\n );\n }\n}\n"],"mappings":"sDAAA,MAAMA,EAAY,IAAM,+hF,MCYXC,EAAMC,EAAA,MAAAD,UAAAE,EALnB,WAAAC,CAAAC,G,sJAOUC,KAAAC,MAAQ,GAMRD,KAAAE,SAAW,MAMXF,KAAAG,YAAc,MAGdH,KAAAI,SAAW,MAGXJ,KAAAK,KAAyC,UAYzCL,KAAAM,YAAc,KACpB,GAAIN,KAAKI,SAAU,OACnBJ,KAAKO,aAAaC,KAAK,CACrBC,MAAOT,KAAKU,cACZT,MAAOD,KAAKC,MACZC,UAAWF,KAAKE,UAChB,EAGIF,KAAAW,cAAiBC,IACvBA,EAAMC,kBACN,GAAIb,KAAKI,SAAU,OACnBJ,KAAKc,cAAcN,KAAK,CAAEC,MAAOT,KAAKU,cAAeT,MAAOD,KAAKC,OAAQ,CAgD5E,CAhEC,iBAAYS,GACV,OAAOV,KAAKS,OAAST,KAAKC,K,CAkB5B,MAAAc,GACE,MAAMC,EAAO,CACXC,EAAA,QAAMC,MAAM,QACVD,EAAA,cAEFA,EAAA,QAAMC,MAAM,QAAQC,KAAK,SACtBnB,KAAKC,cAEDD,KAAKoB,QAAU,UACpBH,EAAA,QAAMC,MAAM,QAAQC,KAAK,SACtBnB,KAAKoB,QAKZ,MAAMC,EAAU,CACdC,KAAM,KACN,cAAetB,KAAKE,SACpB,iBAAkBF,KAAKG,YACvB,CAAC,QAAQH,KAAKK,QAAS,MAKzB,GAAIL,KAAKG,YAAa,CACpB,OACEc,EAAA,QAAMC,MAAOG,EAASF,KAAK,QACzBF,EAAA,UAAQC,MAAM,OAAOK,KAAK,SAASnB,SAAUJ,KAAKI,SAAUoB,QAASxB,KAAKM,aACvEU,GAEHC,EAAA,UAAQC,MAAM,UAAUC,KAAK,UAAUI,KAAK,SAASnB,SAAUJ,KAAKI,SAAQ,aAAc,UAAUJ,KAAKC,QAASuB,QAASxB,KAAKW,eAC9HM,EAAA,OAAKQ,QAAQ,YAAYC,KAAK,OAAOC,OAAO,eAAc,eAAc,MAAK,iBAAgB,QAAO,cAAa,QAC/GV,EAAA,QAAMW,EAAE,2B,CAOlB,OACEX,EAAA,UAAQC,MAAOG,EAASF,KAAK,OAAOI,KAAK,SAAQ,eAAeM,OAAO7B,KAAKE,UAAWE,SAAUJ,KAAKI,SAAUoB,QAASxB,KAAKM,aAC3HU,E","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkEmptyState extends Components.RkEmptyState, HTMLElement {}
4
+ export const RkEmptyState: {
5
+ prototype: RkEmptyState;
6
+ new (): RkEmptyState;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as e,H as t,h as r,t as a}from"./index.js";const s=()=>`:host{display:block;font-family:var(--rk-font);font-size:var(--rk-font-size, 15px)}.empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px;padding:52px 28px;border:1.5px dashed var(--rk-border-strong, #d9c6b8);border-radius:var(--rk-radius-lg, 20px);background:var(--rk-surface-2, #fdf5ef);color:var(--rk-ink, #211a16)}.empty.is-bare{border:0;background:transparent;padding:28px 16px}.empty.tone-error{border-color:var(--rk-danger, #c2410c);background:var(--rk-danger-soft, #fdeae1)}.icon{font-size:2.5rem;line-height:1;margin-bottom:4px}.heading{margin:0;font-family:var(--rk-font-display, serif);font-size:1.25em;font-weight:650;letter-spacing:-0.01em}.message{margin:0;max-width:46ch;color:var(--rk-muted, #857166);line-height:1.55;font-size:0.94em}.empty.tone-error .message{color:var(--rk-danger, #c2410c)}.actions{display:contents}.actions ::slotted(*){margin-top:12px}`;const n=e(class e extends t{constructor(e){super();if(e!==false){this.__registerHost()}this.__attachShadow();this.icon="🍳";this.heading="Nothing here yet";this.tone="neutral";this.bare=false}render(){return r("div",{key:"d770d00625d0f8933704195e975ff96e2599a8a9",class:{empty:true,[`tone-${this.tone}`]:true,"is-bare":this.bare},part:"container",role:this.tone==="error"?"alert":null},r("span",{key:"566dc86da2eaaa9765c3112f381aa409bdcf5198",class:"icon",part:"icon","aria-hidden":"true"},this.icon),r("h3",{key:"9d8e62cc4724b970b6c16dd51797e6c480bf38d2",class:"heading",part:"heading"},this.heading),this.message&&r("p",{key:"b200ce21253e8cd7f9aa73b513030656db956a5e",class:"message",part:"message"},this.message),r("div",{key:"1d04761bf9fa953362826e13be1fc95eebc9067a",class:"actions",part:"actions"},r("slot",{key:"f1302bd354850c09e6fb4b136a32759040b30ecd"})))}static get style(){return s()}},[257,"rk-empty-state",{icon:[1],heading:[1],message:[1],tone:[1],bare:[4]}]);function i(){if(typeof customElements==="undefined"){return}const e=["rk-empty-state"];e.forEach((e=>{switch(e){case"rk-empty-state":if(!customElements.get(a(e))){customElements.define(a(e),n)}break}}))}i();const o=n;const c=i;export{o as RkEmptyState,c as defineCustomElement};
2
+ //# sourceMappingURL=rk-empty-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkEmptyStateCss","RkEmptyState","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","icon","heading","tone","bare","render","h","key","class","empty","part","role","message"],"sources":["src/components/rk-empty-state/rk-empty-state.css?tag=rk-empty-state&encapsulation=shadow","src/components/rk-empty-state/rk-empty-state.tsx"],"sourcesContent":[":host {\n display: block;\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n}\n\n.empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n text-align: center;\n gap: 8px;\n padding: 52px 28px;\n border: 1.5px dashed var(--rk-border-strong, #d9c6b8);\n border-radius: var(--rk-radius-lg, 20px);\n background: var(--rk-surface-2, #fdf5ef);\n color: var(--rk-ink, #211a16);\n}\n\n.empty.is-bare {\n border: 0;\n background: transparent;\n padding: 28px 16px;\n}\n\n.empty.tone-error {\n border-color: var(--rk-danger, #c2410c);\n background: var(--rk-danger-soft, #fdeae1);\n}\n\n.icon {\n font-size: 2.5rem;\n line-height: 1;\n margin-bottom: 4px;\n}\n\n.heading {\n margin: 0;\n font-family: var(--rk-font-display, serif);\n font-size: 1.25em;\n font-weight: 650;\n letter-spacing: -0.01em;\n}\n\n.message {\n margin: 0;\n max-width: 46ch;\n color: var(--rk-muted, #857166);\n line-height: 1.55;\n font-size: 0.94em;\n}\n\n.empty.tone-error .message {\n color: var(--rk-danger, #c2410c);\n}\n\n/* `display: contents` keeps an unused actions slot from adding vertical space. */\n.actions {\n display: contents;\n}\n\n.actions ::slotted(*) {\n margin-top: 12px;\n}\n","import { Component, h, Prop } from '@stencil/core';\n\n/**\n * Placeholder shown when a list has no items, a search returns nothing, or a\n * request fails.\n *\n * @slot - Call-to-action content rendered under the message (buttons, links).\n */\n@Component({\n tag: 'rk-empty-state',\n styleUrl: 'rk-empty-state.css',\n shadow: true,\n})\nexport class RkEmptyState {\n /** Emoji or short glyph shown above the heading. */\n @Prop() icon = '🍳';\n\n /** Bold headline. */\n @Prop() heading = 'Nothing here yet';\n\n /** Supporting sentence. */\n @Prop() message?: string;\n\n /** `error` swaps to a warning treatment. */\n @Prop() tone: 'neutral' | 'error' = 'neutral';\n\n /** Removes the dashed border and reduces padding, for inline use. */\n @Prop() bare = false;\n\n render() {\n return (\n <div class={{ empty: true, [`tone-${this.tone}`]: true, 'is-bare': this.bare }} part=\"container\" role={this.tone === 'error' ? 'alert' : null}>\n <span class=\"icon\" part=\"icon\" aria-hidden=\"true\">\n {this.icon}\n </span>\n <h3 class=\"heading\" part=\"heading\">\n {this.heading}\n </h3>\n {this.message && (\n <p class=\"message\" part=\"message\">\n {this.message}\n </p>\n )}\n <div class=\"actions\" part=\"actions\">\n <slot />\n </div>\n </div>\n );\n }\n}\n"],"mappings":"oDAAA,MAAMA,EAAkB,IAAM,64B,MCajBC,EAAYC,EAAA,MAAAD,UAAAE,EALzB,WAAAC,CAAAC,G,kEAOUC,KAAAC,KAAO,KAGPD,KAAAE,QAAU,mBAMVF,KAAAG,KAA4B,UAG5BH,KAAAI,KAAO,KAsBhB,CApBC,MAAAC,GACE,OACEC,EAAA,OAAAC,IAAA,2CAAKC,MAAO,CAAEC,MAAO,KAAM,CAAC,QAAQT,KAAKG,QAAS,KAAM,UAAWH,KAAKI,MAAQM,KAAK,YAAYC,KAAMX,KAAKG,OAAS,QAAU,QAAU,MACvIG,EAAA,QAAAC,IAAA,2CAAMC,MAAM,OAAOE,KAAK,OAAM,cAAa,QACxCV,KAAKC,MAERK,EAAA,MAAAC,IAAA,2CAAIC,MAAM,UAAUE,KAAK,WACtBV,KAAKE,SAEPF,KAAKY,SACJN,EAAA,KAAAC,IAAA,2CAAGC,MAAM,UAAUE,KAAK,WACrBV,KAAKY,SAGVN,EAAA,OAAAC,IAAA,2CAAKC,MAAM,UAAUE,KAAK,WACxBJ,EAAA,QAAAC,IAAA,8C","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkMealSlot extends Components.RkMealSlot, HTMLElement {}
4
+ export const RkMealSlot: {
5
+ prototype: RkMealSlot;
6
+ new (): RkMealSlot;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as t,H as r,c as e,h as i,t as s}from"./index.js";const o=()=>`:host{display:block;font-family:var(--rk-font);font-size:var(--rk-font-size, 15px);color:var(--rk-ink, #211a16)}.slot{position:relative;width:100%;box-sizing:border-box;border-radius:var(--rk-radius, 14px);transition:border-color var(--rk-transition), background var(--rk-transition), box-shadow var(--rk-transition)}.slot.is-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:86px;padding:12px 10px;border:1.5px dashed var(--rk-border-strong, #d9c6b8);background:transparent;color:var(--rk-muted, #857166);font:inherit;cursor:pointer}.slot.is-empty:hover:not(:disabled){border-color:var(--rk-primary, #d94f1b);background:var(--rk-primary-soft, #fdeee6);color:var(--rk-primary-strong, #b23c11)}.slot.is-empty:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.slot.is-empty:disabled{opacity:0.5;cursor:not-allowed}.plus{font-size:1.3rem;line-height:1;font-weight:300}.empty-label{font-size:0.76em;font-weight:600;text-transform:uppercase;letter-spacing:0.06em}.slot.is-filled{display:flex;flex-direction:column;gap:6px;min-height:86px;padding:10px;border:1px solid var(--rk-border, #ecdfd4);background:var(--rk-surface, #fff);box-shadow:var(--rk-shadow-sm)}.caption{font-size:0.7em;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:var(--rk-muted, #857166)}.main{display:flex;align-items:center;gap:9px;width:100%;padding:0;border:0;background:transparent;text-align:left;font:inherit;color:inherit;cursor:pointer;border-radius:var(--rk-radius-sm, 8px)}.main:hover:not(:disabled) .name{color:var(--rk-primary, #d94f1b)}.main:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.main:disabled{cursor:not-allowed}.thumb{flex:0 0 auto;width:38px;height:38px;border-radius:var(--rk-radius-sm, 8px);object-fit:cover;background:var(--rk-surface-2, #fdf5ef)}.thumb-fallback{display:grid;place-items:center;font-size:1.1rem}.name{font-size:0.87em;font-weight:600;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;transition:color var(--rk-transition)}.extra{display:contents}.extra ::slotted(*){font-size:0.8em;color:var(--rk-muted, #857166)}.controls{position:absolute;top:6px;right:6px;display:flex;gap:3px;opacity:0;transition:opacity var(--rk-transition)}.slot.is-filled:hover .controls,.slot.is-filled:focus-within .controls{opacity:1}.ctrl{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:1px solid var(--rk-border, #ecdfd4);border-radius:50%;background:var(--rk-surface, #fff);color:var(--rk-ink-2, #52443c);cursor:pointer;box-shadow:var(--rk-shadow-sm);transition:background var(--rk-transition), color var(--rk-transition)}.ctrl:hover:not(:disabled){background:var(--rk-surface-2, #fdf5ef);color:var(--rk-primary, #d94f1b)}.ctrl.is-danger:hover:not(:disabled){background:var(--rk-danger-soft, #fdeae1);color:var(--rk-danger, #c2410c)}.ctrl:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.ctrl:disabled{opacity:0.5;cursor:not-allowed}.ctrl svg{width:12px;height:12px}.slot.is-drag-over{border-color:var(--rk-accent, #0f766e) !important;border-style:solid;background:var(--rk-accent-soft, #e2f3f1) !important;box-shadow:0 0 0 3px rgba(15, 118, 110, 0.2)}@media (hover: none){.controls{opacity:1}}@media (prefers-reduced-motion: reduce){.slot,.controls,.ctrl,.name{transition:none}}`;const a=t(class t extends r{constructor(t){super();if(t!==false){this.__registerHost()}this.__attachShadow();this.rkMealAdd=e(this,"rkMealAdd");this.rkMealSwap=e(this,"rkMealSwap");this.rkMealRemove=e(this,"rkMealRemove");this.rkMealOpen=e(this,"rkMealOpen");this.rkMealDrop=e(this,"rkMealDrop");this.disabled=false;this.dragOver=false;this.handleDragOver=t=>{if(this.disabled)return;t.preventDefault();if(t.dataTransfer)t.dataTransfer.dropEffect="copy";this.dragOver=true};this.handleDrop=t=>{t.preventDefault();this.dragOver=false;if(this.disabled)return;const r=t.dataTransfer?.getData("text/plain")??"";if(r)this.rkMealDrop.emit({...this.slotDetail,payload:r})}}get filled(){return!!this.recipeId}get slotDetail(){return{day:this.day,mealType:this.mealType}}get recipeDetail(){return{...this.slotDetail,recipeId:this.recipeId??"",recipeName:this.recipeName??""}}render(){if(!this.filled){return i("button",{class:{slot:true,"is-empty":true,"is-drag-over":this.dragOver},part:"slot",type:"button",disabled:this.disabled,"aria-label":`Add a recipe for ${this.mealLabel??this.mealType} on ${this.day}`,onClick:()=>this.rkMealAdd.emit(this.slotDetail),onDragOver:this.handleDragOver,onDragLeave:()=>this.dragOver=false,onDrop:this.handleDrop},i("span",{class:"plus","aria-hidden":"true"},"+"),i("span",{class:"empty-label"},this.mealLabel??this.mealType))}return i("div",{class:{slot:true,"is-filled":true,"is-drag-over":this.dragOver},part:"slot",onDragOver:this.handleDragOver,onDragLeave:()=>this.dragOver=false,onDrop:this.handleDrop},this.mealLabel&&i("span",{class:"caption",part:"caption"},this.mealLabel),i("button",{class:"main",part:"main",type:"button",disabled:this.disabled,title:this.recipeName,onClick:()=>this.rkMealOpen.emit(this.recipeDetail)},this.recipeImage?i("img",{class:"thumb",src:this.recipeImage,alt:"",loading:"lazy",decoding:"async"}):i("span",{class:"thumb thumb-fallback","aria-hidden":"true"},"🍽️"),i("span",{class:"name",part:"name"},this.recipeName)),i("div",{class:"extra"},i("slot",null)),i("div",{class:"controls",part:"controls"},i("button",{class:"ctrl",type:"button",disabled:this.disabled,"aria-label":`Replace ${this.recipeName}`,title:"Replace",onClick:()=>this.rkMealSwap.emit(this.recipeDetail)},i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round","aria-hidden":"true"},i("path",{d:"M3 12a9 9 0 0 1 15.3-6.4L21 8"}),i("path",{d:"M21 3v5h-5"}),i("path",{d:"M21 12a9 9 0 0 1-15.3 6.4L3 16"}),i("path",{d:"M3 21v-5h5"}))),i("button",{class:"ctrl is-danger",type:"button",disabled:this.disabled,"aria-label":`Remove ${this.recipeName} from ${this.mealLabel??this.mealType}`,title:"Remove",onClick:()=>this.rkMealRemove.emit(this.recipeDetail)},i("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","aria-hidden":"true"},i("path",{d:"M6 6l12 12M18 6 6 18"})))))}static get style(){return o()}},[257,"rk-meal-slot",{day:[1],mealType:[1,"meal-type"],mealLabel:[1,"meal-label"],recipeId:[1,"recipe-id"],recipeName:[1,"recipe-name"],recipeImage:[1,"recipe-image"],disabled:[4],dragOver:[32]}]);function n(){if(typeof customElements==="undefined"){return}const t=["rk-meal-slot"];t.forEach((t=>{switch(t){case"rk-meal-slot":if(!customElements.get(s(t))){customElements.define(s(t),a)}break}}))}n();const l=a;const d=n;export{l as RkMealSlot,d as defineCustomElement};
2
+ //# sourceMappingURL=rk-meal-slot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkMealSlotCss","RkMealSlot","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","disabled","dragOver","handleDragOver","event","preventDefault","dataTransfer","dropEffect","handleDrop","payload","getData","rkMealDrop","emit","slotDetail","filled","recipeId","day","mealType","recipeDetail","recipeName","render","h","class","slot","part","type","mealLabel","onClick","rkMealAdd","onDragOver","onDragLeave","onDrop","title","rkMealOpen","recipeImage","src","alt","loading","decoding","rkMealSwap","viewBox","fill","stroke","d","rkMealRemove"],"sources":["src/components/rk-meal-slot/rk-meal-slot.css?tag=rk-meal-slot&encapsulation=shadow","src/components/rk-meal-slot/rk-meal-slot.tsx"],"sourcesContent":[":host {\n display: block;\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n color: var(--rk-ink, #211a16);\n}\n\n.slot {\n position: relative;\n width: 100%;\n box-sizing: border-box;\n border-radius: var(--rk-radius, 14px);\n transition: border-color var(--rk-transition), background var(--rk-transition), box-shadow var(--rk-transition);\n}\n\n/* ---------- empty ---------- */\n\n.slot.is-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 3px;\n min-height: 86px;\n padding: 12px 10px;\n border: 1.5px dashed var(--rk-border-strong, #d9c6b8);\n background: transparent;\n color: var(--rk-muted, #857166);\n font: inherit;\n cursor: pointer;\n}\n\n.slot.is-empty:hover:not(:disabled) {\n border-color: var(--rk-primary, #d94f1b);\n background: var(--rk-primary-soft, #fdeee6);\n color: var(--rk-primary-strong, #b23c11);\n}\n\n.slot.is-empty:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.slot.is-empty:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.plus {\n font-size: 1.3rem;\n line-height: 1;\n font-weight: 300;\n}\n\n.empty-label {\n font-size: 0.76em;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n/* ---------- filled ---------- */\n\n.slot.is-filled {\n display: flex;\n flex-direction: column;\n gap: 6px;\n min-height: 86px;\n padding: 10px;\n border: 1px solid var(--rk-border, #ecdfd4);\n background: var(--rk-surface, #fff);\n box-shadow: var(--rk-shadow-sm);\n}\n\n.caption {\n font-size: 0.7em;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.07em;\n color: var(--rk-muted, #857166);\n}\n\n.main {\n display: flex;\n align-items: center;\n gap: 9px;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n text-align: left;\n font: inherit;\n color: inherit;\n cursor: pointer;\n border-radius: var(--rk-radius-sm, 8px);\n}\n\n.main:hover:not(:disabled) .name {\n color: var(--rk-primary, #d94f1b);\n}\n\n.main:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.main:disabled {\n cursor: not-allowed;\n}\n\n.thumb {\n flex: 0 0 auto;\n width: 38px;\n height: 38px;\n border-radius: var(--rk-radius-sm, 8px);\n object-fit: cover;\n background: var(--rk-surface-2, #fdf5ef);\n}\n\n.thumb-fallback {\n display: grid;\n place-items: center;\n font-size: 1.1rem;\n}\n\n.name {\n font-size: 0.87em;\n font-weight: 600;\n line-height: 1.3;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n transition: color var(--rk-transition);\n}\n\n.extra {\n display: contents;\n}\n\n.extra ::slotted(*) {\n font-size: 0.8em;\n color: var(--rk-muted, #857166);\n}\n\n.controls {\n position: absolute;\n top: 6px;\n right: 6px;\n display: flex;\n gap: 3px;\n opacity: 0;\n transition: opacity var(--rk-transition);\n}\n\n.slot.is-filled:hover .controls,\n.slot.is-filled:focus-within .controls {\n opacity: 1;\n}\n\n.ctrl {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0;\n border: 1px solid var(--rk-border, #ecdfd4);\n border-radius: 50%;\n background: var(--rk-surface, #fff);\n color: var(--rk-ink-2, #52443c);\n cursor: pointer;\n box-shadow: var(--rk-shadow-sm);\n transition: background var(--rk-transition), color var(--rk-transition);\n}\n\n.ctrl:hover:not(:disabled) {\n background: var(--rk-surface-2, #fdf5ef);\n color: var(--rk-primary, #d94f1b);\n}\n\n.ctrl.is-danger:hover:not(:disabled) {\n background: var(--rk-danger-soft, #fdeae1);\n color: var(--rk-danger, #c2410c);\n}\n\n.ctrl:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.ctrl:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.ctrl svg {\n width: 12px;\n height: 12px;\n}\n\n/* ---------- drag & drop ---------- */\n\n.slot.is-drag-over {\n border-color: var(--rk-accent, #0f766e) !important;\n border-style: solid;\n background: var(--rk-accent-soft, #e2f3f1) !important;\n box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.2);\n}\n\n/* Touch devices have no hover, so the controls stay visible. */\n@media (hover: none) {\n .controls {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .slot,\n .controls,\n .ctrl,\n .name {\n transition: none;\n }\n}\n","import { Component, Event, EventEmitter, h, Prop, State } from '@stencil/core';\n\nexport interface RkMealSlotDetail {\n day: string;\n mealType: string;\n}\n\nexport interface RkMealRecipeDetail extends RkMealSlotDetail {\n recipeId: string;\n recipeName: string;\n}\n\nexport interface RkMealDropDetail extends RkMealSlotDetail {\n /** Raw `text/plain` payload from the drag operation. */\n payload: string;\n}\n\n/**\n * One cell of the weekly planner grid: either an empty \"add\" target or a filled\n * slot showing the planned recipe. Doubles as a drop zone for drag-and-drop\n * planning.\n *\n * @slot - Extra content rendered under the recipe name (e.g. serving notes).\n */\n@Component({\n tag: 'rk-meal-slot',\n styleUrl: 'rk-meal-slot.css',\n shadow: true,\n})\nexport class RkMealSlot {\n /** Day key this slot belongs to, e.g. `monday`. Echoed in event payloads. */\n @Prop() day!: string;\n\n /** Meal type key, e.g. `breakfast`. Echoed in event payloads. */\n @Prop() mealType!: string;\n\n /** Human-readable meal label shown as the slot caption. */\n @Prop() mealLabel?: string;\n\n /** Id of the planned recipe. Empty means the slot is free. */\n @Prop() recipeId?: string;\n\n /** Title of the planned recipe. */\n @Prop() recipeName?: string;\n\n /** Thumbnail of the planned recipe. */\n @Prop() recipeImage?: string;\n\n /** Disables interaction. */\n @Prop() disabled = false;\n\n /** Emitted when an empty slot is activated — the host opens a recipe picker. */\n @Event({ eventName: 'rkMealAdd' }) rkMealAdd!: EventEmitter<RkMealSlotDetail>;\n\n /** Emitted when the planned recipe should be replaced. */\n @Event({ eventName: 'rkMealSwap' }) rkMealSwap!: EventEmitter<RkMealRecipeDetail>;\n\n /** Emitted when the planned recipe should be cleared. */\n @Event({ eventName: 'rkMealRemove' }) rkMealRemove!: EventEmitter<RkMealRecipeDetail>;\n\n /** Emitted when the planned recipe is activated — the host navigates. */\n @Event({ eventName: 'rkMealOpen' }) rkMealOpen!: EventEmitter<RkMealRecipeDetail>;\n\n /** Emitted when a recipe is dropped onto this slot. */\n @Event({ eventName: 'rkMealDrop' }) rkMealDrop!: EventEmitter<RkMealDropDetail>;\n\n @State() private dragOver = false;\n\n private get filled() {\n return !!this.recipeId;\n }\n\n private get slotDetail(): RkMealSlotDetail {\n return { day: this.day, mealType: this.mealType };\n }\n\n private get recipeDetail(): RkMealRecipeDetail {\n return { ...this.slotDetail, recipeId: this.recipeId ?? '', recipeName: this.recipeName ?? '' };\n }\n\n private handleDragOver = (event: DragEvent) => {\n if (this.disabled) return;\n // Preventing default is what marks this element as a valid drop target.\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n this.dragOver = true;\n };\n\n private handleDrop = (event: DragEvent) => {\n event.preventDefault();\n this.dragOver = false;\n if (this.disabled) return;\n const payload = event.dataTransfer?.getData('text/plain') ?? '';\n if (payload) this.rkMealDrop.emit({ ...this.slotDetail, payload });\n };\n\n render() {\n if (!this.filled) {\n return (\n <button\n class={{ slot: true, 'is-empty': true, 'is-drag-over': this.dragOver }}\n part=\"slot\"\n type=\"button\"\n disabled={this.disabled}\n aria-label={`Add a recipe for ${this.mealLabel ?? this.mealType} on ${this.day}`}\n onClick={() => this.rkMealAdd.emit(this.slotDetail)}\n onDragOver={this.handleDragOver}\n onDragLeave={() => (this.dragOver = false)}\n onDrop={this.handleDrop}\n >\n <span class=\"plus\" aria-hidden=\"true\">\n +\n </span>\n <span class=\"empty-label\">{this.mealLabel ?? this.mealType}</span>\n </button>\n );\n }\n\n return (\n <div\n class={{ slot: true, 'is-filled': true, 'is-drag-over': this.dragOver }}\n part=\"slot\"\n onDragOver={this.handleDragOver}\n onDragLeave={() => (this.dragOver = false)}\n onDrop={this.handleDrop}\n >\n {this.mealLabel && (\n <span class=\"caption\" part=\"caption\">\n {this.mealLabel}\n </span>\n )}\n\n <button\n class=\"main\"\n part=\"main\"\n type=\"button\"\n disabled={this.disabled}\n title={this.recipeName}\n onClick={() => this.rkMealOpen.emit(this.recipeDetail)}\n >\n {this.recipeImage ? (\n <img class=\"thumb\" src={this.recipeImage} alt=\"\" loading=\"lazy\" decoding=\"async\" />\n ) : (\n <span class=\"thumb thumb-fallback\" aria-hidden=\"true\">\n 🍽️\n </span>\n )}\n <span class=\"name\" part=\"name\">\n {this.recipeName}\n </span>\n </button>\n\n <div class=\"extra\">\n <slot />\n </div>\n\n <div class=\"controls\" part=\"controls\">\n <button class=\"ctrl\" type=\"button\" disabled={this.disabled} aria-label={`Replace ${this.recipeName}`} title=\"Replace\" onClick={() => this.rkMealSwap.emit(this.recipeDetail)}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M3 12a9 9 0 0 1 15.3-6.4L21 8\" />\n <path d=\"M21 3v5h-5\" />\n <path d=\"M21 12a9 9 0 0 1-15.3 6.4L3 16\" />\n <path d=\"M3 21v-5h5\" />\n </svg>\n </button>\n <button\n class=\"ctrl is-danger\"\n type=\"button\"\n disabled={this.disabled}\n aria-label={`Remove ${this.recipeName} from ${this.mealLabel ?? this.mealType}`}\n title=\"Remove\"\n onClick={() => this.rkMealRemove.emit(this.recipeDetail)}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6 6 18\" />\n </svg>\n </button>\n </div>\n </div>\n );\n }\n}\n"],"mappings":"2DAAA,MAAMA,EAAgB,IAAM,yzG,MC6BfC,EAAUC,EAAA,MAAAD,UAAAE,EALvB,WAAAC,CAAAC,G,6PAyBUC,KAAAC,SAAW,MAiBFD,KAAAE,SAAW,MAcpBF,KAAAG,eAAkBC,IACxB,GAAIJ,KAAKC,SAAU,OAEnBG,EAAMC,iBACN,GAAID,EAAME,aAAcF,EAAME,aAAaC,WAAa,OACxDP,KAAKE,SAAW,IAAI,EAGdF,KAAAQ,WAAcJ,IACpBA,EAAMC,iBACNL,KAAKE,SAAW,MAChB,GAAIF,KAAKC,SAAU,OACnB,MAAMQ,EAAUL,EAAME,cAAcI,QAAQ,eAAiB,GAC7D,GAAID,EAAST,KAAKW,WAAWC,KAAK,IAAKZ,KAAKa,WAAYJ,WAAU,CAwFrE,CAjHC,UAAYK,GACV,QAASd,KAAKe,Q,CAGhB,cAAYF,GACV,MAAO,CAAEG,IAAKhB,KAAKgB,IAAKC,SAAUjB,KAAKiB,S,CAGzC,gBAAYC,GACV,MAAO,IAAKlB,KAAKa,WAAYE,SAAUf,KAAKe,UAAY,GAAII,WAAYnB,KAAKmB,YAAc,G,CAmB7F,MAAAC,GACE,IAAKpB,KAAKc,OAAQ,CAChB,OACEO,EAAA,UACEC,MAAO,CAAEC,KAAM,KAAM,WAAY,KAAM,eAAgBvB,KAAKE,UAC5DsB,KAAK,OACLC,KAAK,SACLxB,SAAUD,KAAKC,SAAQ,aACX,oBAAoBD,KAAK0B,WAAa1B,KAAKiB,eAAejB,KAAKgB,MAC3EW,QAAS,IAAM3B,KAAK4B,UAAUhB,KAAKZ,KAAKa,YACxCgB,WAAY7B,KAAKG,eACjB2B,YAAa,IAAO9B,KAAKE,SAAW,MACpC6B,OAAQ/B,KAAKQ,YAEba,EAAA,QAAMC,MAAM,OAAM,cAAa,QAAM,KAGrCD,EAAA,QAAMC,MAAM,eAAetB,KAAK0B,WAAa1B,KAAKiB,U,CAKxD,OACEI,EAAA,OACEC,MAAO,CAAEC,KAAM,KAAM,YAAa,KAAM,eAAgBvB,KAAKE,UAC7DsB,KAAK,OACLK,WAAY7B,KAAKG,eACjB2B,YAAa,IAAO9B,KAAKE,SAAW,MACpC6B,OAAQ/B,KAAKQ,YAEZR,KAAK0B,WACJL,EAAA,QAAMC,MAAM,UAAUE,KAAK,WACxBxB,KAAK0B,WAIVL,EAAA,UACEC,MAAM,OACNE,KAAK,OACLC,KAAK,SACLxB,SAAUD,KAAKC,SACf+B,MAAOhC,KAAKmB,WACZQ,QAAS,IAAM3B,KAAKiC,WAAWrB,KAAKZ,KAAKkB,eAExClB,KAAKkC,YACJb,EAAA,OAAKC,MAAM,QAAQa,IAAKnC,KAAKkC,YAAaE,IAAI,GAAGC,QAAQ,OAAOC,SAAS,UAEzEjB,EAAA,QAAMC,MAAM,uBAAsB,cAAa,QAAM,OAIvDD,EAAA,QAAMC,MAAM,OAAOE,KAAK,QACrBxB,KAAKmB,aAIVE,EAAA,OAAKC,MAAM,SACTD,EAAA,cAGFA,EAAA,OAAKC,MAAM,WAAWE,KAAK,YACzBH,EAAA,UAAQC,MAAM,OAAOG,KAAK,SAASxB,SAAUD,KAAKC,SAAQ,aAAc,WAAWD,KAAKmB,aAAca,MAAM,UAAUL,QAAS,IAAM3B,KAAKuC,WAAW3B,KAAKZ,KAAKkB,eAC7JG,EAAA,OAAKmB,QAAQ,YAAYC,KAAK,OAAOC,OAAO,eAAc,eAAc,IAAG,iBAAgB,QAAO,kBAAiB,QAAO,cAAa,QACrIrB,EAAA,QAAMsB,EAAE,kCACRtB,EAAA,QAAMsB,EAAE,eACRtB,EAAA,QAAMsB,EAAE,mCACRtB,EAAA,QAAMsB,EAAE,iBAGZtB,EAAA,UACEC,MAAM,iBACNG,KAAK,SACLxB,SAAUD,KAAKC,SAAQ,aACX,UAAUD,KAAKmB,mBAAmBnB,KAAK0B,WAAa1B,KAAKiB,WACrEe,MAAM,SACNL,QAAS,IAAM3B,KAAK4C,aAAahC,KAAKZ,KAAKkB,eAE3CG,EAAA,OAAKmB,QAAQ,YAAYC,KAAK,OAAOC,OAAO,eAAc,eAAc,IAAG,iBAAgB,QAAO,cAAa,QAC7GrB,EAAA,QAAMsB,EAAE,4B","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkModal extends Components.RkModal, HTMLElement {}
4
+ export const RkModal: {
5
+ prototype: RkModal;
6
+ new (): RkModal;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as e,H as t,c as i,h as r,a as s,t as a}from"./index.js";const o=()=>`:host{font-family:var(--rk-font);font-size:var(--rk-font-size, 15px);color:var(--rk-ink, #211a16)}.backdrop{position:fixed;inset:0;z-index:var(--rk-z-modal, 1000);display:flex;align-items:center;justify-content:center;padding:20px;background:rgba(24, 17, 13, 0.5);backdrop-filter:blur(3px);animation:rk-fade-in 140ms ease-out;overflow-y:auto}.panel{display:flex;flex-direction:column;width:100%;max-height:calc(100vh - 40px);background:var(--rk-surface, #fff);border-radius:var(--rk-radius-lg, 20px);box-shadow:var(--rk-shadow-lg);overflow:hidden;animation:rk-pop-in 180ms cubic-bezier(0.2, 0, 0.2, 1)}.panel:focus{outline:none}.size-sm{max-width:420px}.size-md{max-width:620px}.size-lg{max-width:880px}.header{display:flex;align-items:flex-start;gap:16px;padding:22px 24px 16px;border-bottom:1px solid var(--rk-border, #ecdfd4);flex:0 0 auto}.titles{flex:1 1 auto;min-width:0}.heading{margin:0;font-family:var(--rk-font-display, serif);font-size:1.32em;font-weight:650;letter-spacing:-0.015em;line-height:1.25}.subheading{margin:5px 0 0;font-size:0.9em;color:var(--rk-muted, #857166);line-height:1.5}.close{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border:0;border-radius:50%;background:var(--rk-surface-2, #fdf5ef);color:var(--rk-ink-2, #52443c);cursor:pointer;transition:background var(--rk-transition), color var(--rk-transition)}.close:hover{background:var(--rk-danger-soft, #fdeae1);color:var(--rk-danger, #c2410c)}.close:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.close svg{width:16px;height:16px}.body{padding:20px 24px;overflow-y:auto;flex:1 1 auto;line-height:1.6}.footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:16px 24px;border-top:1px solid var(--rk-border, #ecdfd4);background:var(--rk-surface-2, #fdf5ef);flex:0 0 auto}.footer.is-empty{display:none}@keyframes rk-fade-in{from{opacity:0}}@keyframes rk-pop-in{from{opacity:0;transform:translateY(12px) scale(0.98)}}@media (max-width: 560px){.backdrop{padding:0;align-items:flex-end}.panel{border-radius:var(--rk-radius-lg, 20px) var(--rk-radius-lg, 20px) 0 0;max-height:92vh;max-width:none}}@media (prefers-reduced-motion: reduce){.backdrop,.panel{animation:none}}`;const n=e(class e extends t{constructor(e){super();if(e!==false){this.__registerHost()}this.__attachShadow();this.rkModalClose=i(this,"rkModalClose");this.open=false;this.heading="";this.size="md";this.dismissible=true;this.hasFooter=false;this.syncFooterSlot=()=>{this.hasFooter=Array.from(this.host.children).some((e=>e.getAttribute("slot")==="footer"))};this.handleGlobalKeyDown=e=>{if(!this.open)return;if(e.key==="Escape"&&this.dismissible){e.preventDefault();this.rkModalClose.emit();return}if(e.key==="Tab"){const t=this.focusableElements();if(t.length===0)return;const i=t[0];const r=t[t.length-1];const s=this.host.shadowRoot?.activeElement??document.activeElement;if(e.shiftKey&&s===i){e.preventDefault();r.focus()}else if(!e.shiftKey&&s===r){e.preventDefault();i.focus()}}};this.handleBackdrop=e=>{if(!this.dismissible)return;if(e.target===e.currentTarget)this.rkModalClose.emit()}}onOpenChange(e,t){if(e===t)return;if(e){this.previouslyFocused=document.activeElement;document.addEventListener("keydown",this.handleGlobalKeyDown);this.lockScroll(true);requestAnimationFrame((()=>this.focusFirst()))}else{document.removeEventListener("keydown",this.handleGlobalKeyDown);this.lockScroll(false);this.previouslyFocused?.focus?.();this.previouslyFocused=undefined}}componentWillLoad(){this.syncFooterSlot()}componentDidLoad(){if(this.open)this.onOpenChange(true,false)}disconnectedCallback(){document.removeEventListener("keydown",this.handleGlobalKeyDown);this.lockScroll(false)}lockScroll(e){if(typeof document==="undefined")return;document.documentElement.style.overflow=e?"hidden":""}focusableElements(){if(!this.panelEl)return[];const e='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';const t=Array.from(this.panelEl.querySelectorAll(e));const i=Array.from(this.host.querySelectorAll(e));return[...t,...i].filter((e=>e.offsetParent!==null||e===document.activeElement))}focusFirst(){const[e]=this.focusableElements();(e??this.panelEl)?.focus?.()}render(){if(!this.open)return r(s,{"aria-hidden":"true"});return r(s,null,r("div",{class:"backdrop",part:"backdrop",onClick:this.handleBackdrop},r("div",{class:{panel:true,[`size-${this.size}`]:true},part:"panel",role:"dialog","aria-modal":"true","aria-label":this.heading||"Dialog",tabindex:-1,ref:e=>this.panelEl=e},r("header",{class:"header",part:"header"},r("slot",{name:"header"},r("div",{class:"titles"},r("h2",{class:"heading",part:"heading"},this.heading),this.subheading&&r("p",{class:"subheading"},this.subheading))),this.dismissible&&r("button",{class:"close",part:"close",type:"button","aria-label":"Close dialog",onClick:()=>this.rkModalClose.emit()},r("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","aria-hidden":"true"},r("path",{d:"M6 6l12 12M18 6 6 18"})))),r("div",{class:"body",part:"body"},r("slot",null)),r("footer",{class:{footer:true,"is-empty":!this.hasFooter},part:"footer"},r("slot",{name:"footer",onSlotchange:this.syncFooterSlot})))))}get host(){return this}static get watchers(){return{open:[{onOpenChange:0}]}}static get style(){return o()}},[257,"rk-modal",{open:[4],heading:[1],subheading:[1],size:[1],dismissible:[4],hasFooter:[32]},undefined,{open:[{onOpenChange:0}]}]);function d(){if(typeof customElements==="undefined"){return}const e=["rk-modal"];e.forEach((e=>{switch(e){case"rk-modal":if(!customElements.get(a(e))){customElements.define(a(e),n)}break}}))}d();const l=n;const c=d;export{l as RkModal,c as defineCustomElement};
2
+ //# sourceMappingURL=rk-modal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkModalCss","RkModal","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","open","heading","size","dismissible","hasFooter","syncFooterSlot","Array","from","host","children","some","node","getAttribute","handleGlobalKeyDown","event","key","preventDefault","rkModalClose","emit","focusable","focusableElements","length","first","last","active","shadowRoot","activeElement","document","shiftKey","focus","handleBackdrop","target","currentTarget","onOpenChange","isOpen","wasOpen","previouslyFocused","addEventListener","lockScroll","requestAnimationFrame","focusFirst","removeEventListener","undefined","componentWillLoad","componentDidLoad","disconnectedCallback","locked","documentElement","style","overflow","panelEl","selector","inShadow","querySelectorAll","inLight","filter","el","offsetParent","render","h","Host","class","part","onClick","panel","role","tabindex","ref","name","subheading","type","viewBox","fill","stroke","d","footer","onSlotchange"],"sources":["src/components/rk-modal/rk-modal.css?tag=rk-modal&encapsulation=shadow","src/components/rk-modal/rk-modal.tsx"],"sourcesContent":[":host {\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n color: var(--rk-ink, #211a16);\n}\n\n.backdrop {\n position: fixed;\n inset: 0;\n z-index: var(--rk-z-modal, 1000);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 20px;\n background: rgba(24, 17, 13, 0.5);\n backdrop-filter: blur(3px);\n animation: rk-fade-in 140ms ease-out;\n overflow-y: auto;\n}\n\n.panel {\n display: flex;\n flex-direction: column;\n width: 100%;\n max-height: calc(100vh - 40px);\n background: var(--rk-surface, #fff);\n border-radius: var(--rk-radius-lg, 20px);\n box-shadow: var(--rk-shadow-lg);\n overflow: hidden;\n animation: rk-pop-in 180ms cubic-bezier(0.2, 0, 0.2, 1);\n}\n\n.panel:focus {\n outline: none;\n}\n\n.size-sm {\n max-width: 420px;\n}\n\n.size-md {\n max-width: 620px;\n}\n\n.size-lg {\n max-width: 880px;\n}\n\n.header {\n display: flex;\n align-items: flex-start;\n gap: 16px;\n padding: 22px 24px 16px;\n border-bottom: 1px solid var(--rk-border, #ecdfd4);\n flex: 0 0 auto;\n}\n\n.titles {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.heading {\n margin: 0;\n font-family: var(--rk-font-display, serif);\n font-size: 1.32em;\n font-weight: 650;\n letter-spacing: -0.015em;\n line-height: 1.25;\n}\n\n.subheading {\n margin: 5px 0 0;\n font-size: 0.9em;\n color: var(--rk-muted, #857166);\n line-height: 1.5;\n}\n\n.close {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n height: 34px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n background: var(--rk-surface-2, #fdf5ef);\n color: var(--rk-ink-2, #52443c);\n cursor: pointer;\n transition: background var(--rk-transition), color var(--rk-transition);\n}\n\n.close:hover {\n background: var(--rk-danger-soft, #fdeae1);\n color: var(--rk-danger, #c2410c);\n}\n\n.close:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.close svg {\n width: 16px;\n height: 16px;\n}\n\n.body {\n padding: 20px 24px;\n overflow-y: auto;\n flex: 1 1 auto;\n line-height: 1.6;\n}\n\n.footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n padding: 16px 24px;\n border-top: 1px solid var(--rk-border, #ecdfd4);\n background: var(--rk-surface-2, #fdf5ef);\n flex: 0 0 auto;\n}\n\n.footer.is-empty {\n display: none;\n}\n\n@keyframes rk-fade-in {\n from {\n opacity: 0;\n }\n}\n\n@keyframes rk-pop-in {\n from {\n opacity: 0;\n transform: translateY(12px) scale(0.98);\n }\n}\n\n@media (max-width: 560px) {\n .backdrop {\n padding: 0;\n align-items: flex-end;\n }\n\n .panel {\n border-radius: var(--rk-radius-lg, 20px) var(--rk-radius-lg, 20px) 0 0;\n max-height: 92vh;\n max-width: none;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .backdrop,\n .panel {\n animation: none;\n }\n}\n","import { Component, Element, Event, EventEmitter, h, Host, Prop, State, Watch } from '@stencil/core';\n\n/**\n * An accessible dialog with a backdrop, Escape handling and focus restoration.\n *\n * The component is presentational: it emits `rkModalClose` and lets the host\n * application own the `open` state.\n *\n * @slot - Dialog body.\n * @slot header - Replaces the default heading row entirely.\n * @slot footer - Action row pinned to the bottom of the dialog.\n */\n@Component({\n tag: 'rk-modal',\n styleUrl: 'rk-modal.css',\n shadow: true,\n})\nexport class RkModal {\n @Element() host!: HTMLElement;\n\n /** Controls visibility. */\n @Prop() open = false;\n\n /** Heading text for the default header. */\n @Prop() heading = '';\n\n /** Optional supporting line under the heading. */\n @Prop() subheading?: string;\n\n /** Dialog width preset. */\n @Prop() size: 'sm' | 'md' | 'lg' = 'md';\n\n /** Set to false to require an explicit action to dismiss. */\n @Prop() dismissible = true;\n\n /** Emitted when the user requests dismissal (X, backdrop or Escape). */\n @Event({ eventName: 'rkModalClose' }) rkModalClose!: EventEmitter<void>;\n\n @State() private hasFooter = false;\n\n private previouslyFocused?: HTMLElement;\n private panelEl?: HTMLElement;\n\n /** Collapses the footer region when no action row was projected into it. */\n private syncFooterSlot = () => {\n this.hasFooter = Array.from(this.host.children).some(node => node.getAttribute('slot') === 'footer');\n };\n\n @Watch('open')\n protected onOpenChange(isOpen: boolean, wasOpen: boolean) {\n if (isOpen === wasOpen) return;\n\n if (isOpen) {\n this.previouslyFocused = document.activeElement as HTMLElement;\n document.addEventListener('keydown', this.handleGlobalKeyDown);\n this.lockScroll(true);\n // Wait a frame so the panel exists before moving focus into it.\n requestAnimationFrame(() => this.focusFirst());\n } else {\n document.removeEventListener('keydown', this.handleGlobalKeyDown);\n this.lockScroll(false);\n this.previouslyFocused?.focus?.();\n this.previouslyFocused = undefined;\n }\n }\n\n componentWillLoad() {\n this.syncFooterSlot();\n }\n\n componentDidLoad() {\n if (this.open) this.onOpenChange(true, false);\n }\n\n disconnectedCallback() {\n document.removeEventListener('keydown', this.handleGlobalKeyDown);\n this.lockScroll(false);\n }\n\n private lockScroll(locked: boolean) {\n if (typeof document === 'undefined') return;\n document.documentElement.style.overflow = locked ? 'hidden' : '';\n }\n\n private focusableElements(): HTMLElement[] {\n if (!this.panelEl) return [];\n const selector = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n // Slotted content lives in the light DOM, so both trees have to be queried.\n const inShadow = Array.from(this.panelEl.querySelectorAll<HTMLElement>(selector));\n const inLight = Array.from(this.host.querySelectorAll<HTMLElement>(selector));\n return [...inShadow, ...inLight].filter(el => el.offsetParent !== null || el === document.activeElement);\n }\n\n private focusFirst() {\n const [first] = this.focusableElements();\n (first ?? this.panelEl)?.focus?.();\n }\n\n private handleGlobalKeyDown = (event: KeyboardEvent) => {\n if (!this.open) return;\n\n if (event.key === 'Escape' && this.dismissible) {\n event.preventDefault();\n this.rkModalClose.emit();\n return;\n }\n\n if (event.key === 'Tab') {\n const focusable = this.focusableElements();\n if (focusable.length === 0) return;\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const active = (this.host.shadowRoot?.activeElement ?? document.activeElement) as HTMLElement;\n\n if (event.shiftKey && active === first) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && active === last) {\n event.preventDefault();\n first.focus();\n }\n }\n };\n\n private handleBackdrop = (event: MouseEvent) => {\n if (!this.dismissible) return;\n if (event.target === event.currentTarget) this.rkModalClose.emit();\n };\n\n render() {\n if (!this.open) return <Host aria-hidden=\"true\" />;\n\n return (\n <Host>\n <div class=\"backdrop\" part=\"backdrop\" onClick={this.handleBackdrop}>\n <div\n class={{ panel: true, [`size-${this.size}`]: true }}\n part=\"panel\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={this.heading || 'Dialog'}\n tabindex={-1}\n ref={el => (this.panelEl = el)}\n >\n <header class=\"header\" part=\"header\">\n <slot name=\"header\">\n <div class=\"titles\">\n <h2 class=\"heading\" part=\"heading\">\n {this.heading}\n </h2>\n {this.subheading && <p class=\"subheading\">{this.subheading}</p>}\n </div>\n </slot>\n\n {this.dismissible && (\n <button class=\"close\" part=\"close\" type=\"button\" aria-label=\"Close dialog\" onClick={() => this.rkModalClose.emit()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6 6 18\" />\n </svg>\n </button>\n )}\n </header>\n\n <div class=\"body\" part=\"body\">\n <slot />\n </div>\n\n <footer class={{ footer: true, 'is-empty': !this.hasFooter }} part=\"footer\">\n <slot name=\"footer\" onSlotchange={this.syncFooterSlot} />\n </footer>\n </div>\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkRating extends Components.RkRating, HTMLElement {}
4
+ export const RkRating: {
5
+ prototype: RkRating;
6
+ new (): RkRating;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as t,H as s,c as r,h as a,a as i,t as e}from"./index.js";const n=()=>`:host{display:inline-block;font-family:var(--rk-font);--rk-star-size:18px}.stars{display:inline-flex;align-items:center;gap:2px;border-radius:var(--rk-radius-sm, 8px)}.stars:not(.is-readonly){cursor:pointer}.stars:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.star-wrap{display:inline-flex;padding:1px;transition:transform var(--rk-transition)}.stars:not(.is-readonly) .star-wrap:hover{transform:scale(1.15)}.star{width:var(--rk-star-size);height:var(--rk-star-size);display:block}.star-bg{fill:none;stroke:var(--rk-border-strong, #d9c6b8);stroke-width:1.6}.star-fg{fill:var(--rk-warning, #a16207);stroke:var(--rk-warning, #a16207);stroke-width:1.2}.value{margin-left:7px;font-size:0.85em;font-weight:600;color:var(--rk-ink-2, #52443c);font-variant-numeric:tabular-nums}.count{margin-left:4px;font-weight:500;color:var(--rk-muted, #857166)}@media (prefers-reduced-motion: reduce){.star-wrap,.stars:not(.is-readonly) .star-wrap:hover{transition:none;transform:none}}`;const o=t(class t extends s{constructor(t){super();if(t!==false){this.__registerHost()}this.__attachShadow();this.rkRatingChange=r(this,"rkRatingChange");this.value=0;this.max=5;this.readonly=false;this.size=18;this.label="Rating";this.showValue=false;this.hovered=0;this.handleKeyDown=t=>{if(this.readonly)return;const s=t.key==="ArrowRight"||t.key==="ArrowUp"?1:t.key==="ArrowLeft"||t.key==="ArrowDown"?-1:0;if(s===0)return;t.preventDefault();const r=Math.min(this.max,Math.max(0,Math.round(this.value)+s));this.value=r;this.rkRatingChange.emit(r)}}select(t){if(this.readonly)return;const s=t===this.value?0:t;this.value=s;this.rkRatingChange.emit(s)}render(){const t=this.hovered||this.value;const s=Array.from({length:Math.max(1,Math.round(this.max))},((t,s)=>s+1));return a(i,{key:"2147d57f9887cec317ac42156632a11a92d031bd",style:{"--rk-star-size":`${this.size}px`}},a("div",{key:"8b6ed7883e64adbebb6cb00166ef1dc3e63d8b6f",class:{stars:true,"is-readonly":this.readonly},part:"stars",role:this.readonly?"img":"slider","aria-label":`${this.label}: ${this.value} out of ${this.max}`,"aria-valuenow":this.readonly?null:String(this.value),"aria-valuemin":this.readonly?null:"0","aria-valuemax":this.readonly?null:String(this.max),tabindex:this.readonly?null:0,onKeyDown:this.handleKeyDown,onMouseLeave:()=>this.hovered=0},s.map((s=>{const r=this.readonly?Math.min(1,Math.max(0,this.value-(s-1))):s<=t?1:0;return a("span",{class:"star-wrap",key:s,onMouseEnter:()=>!this.readonly&&(this.hovered=s),onClick:()=>this.select(s),"aria-hidden":"true"},a("svg",{class:"star",viewBox:"0 0 24 24"},a("path",{class:"star-bg",d:"M12 2.6l2.86 5.98 6.54.87-4.8 4.5 1.2 6.45L12 17.3l-5.8 3.1 1.2-6.45-4.8-4.5 6.54-.87z"}),a("clipPath",{id:`clip-${s}`},a("rect",{x:"0",y:"0",width:24*r,height:"24"})),a("path",{class:"star-fg","clip-path":`url(#clip-${s})`,d:"M12 2.6l2.86 5.98 6.54.87-4.8 4.5 1.2 6.45L12 17.3l-5.8 3.1 1.2-6.45-4.8-4.5 6.54-.87z"})))})),this.showValue&&a("span",{key:"0f3fd486aca3d9c05df656e723eeb6a30a7469c2",class:"value",part:"value"},this.value?this.value.toFixed(1):"—",typeof this.count==="number"&&a("span",{key:"40a193f04a145644556dad621fcc3ee65fb101b3",class:"count"},"(",this.count,")"))))}static get style(){return n()}},[1,"rk-rating",{value:[1026],max:[2],readonly:[4],size:[2],label:[1],showValue:[4,"show-value"],count:[2],hovered:[32]}]);function h(){if(typeof customElements==="undefined"){return}const t=["rk-rating"];t.forEach((t=>{switch(t){case"rk-rating":if(!customElements.get(e(t))){customElements.define(e(t),o)}break}}))}h();const l=o;const c=h;export{l as RkRating,c as defineCustomElement};
2
+ //# sourceMappingURL=rk-rating.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkRatingCss","RkRating","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","value","max","readonly","size","label","showValue","hovered","handleKeyDown","event","step","key","preventDefault","next","Math","min","round","rkRatingChange","emit","select","resolved","render","active","stars","Array","from","length","_","index","h","Host","style","class","part","role","String","tabindex","onKeyDown","onMouseLeave","map","star","fill","onMouseEnter","onClick","viewBox","d","id","x","y","width","height","toFixed","count"],"sources":["src/components/rk-rating/rk-rating.css?tag=rk-rating&encapsulation=shadow","src/components/rk-rating/rk-rating.tsx"],"sourcesContent":[":host {\n display: inline-block;\n font-family: var(--rk-font);\n --rk-star-size: 18px;\n}\n\n.stars {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n border-radius: var(--rk-radius-sm, 8px);\n}\n\n.stars:not(.is-readonly) {\n cursor: pointer;\n}\n\n.stars:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.star-wrap {\n display: inline-flex;\n padding: 1px;\n transition: transform var(--rk-transition);\n}\n\n.stars:not(.is-readonly) .star-wrap:hover {\n transform: scale(1.15);\n}\n\n.star {\n width: var(--rk-star-size);\n height: var(--rk-star-size);\n display: block;\n}\n\n.star-bg {\n fill: none;\n stroke: var(--rk-border-strong, #d9c6b8);\n stroke-width: 1.6;\n}\n\n.star-fg {\n fill: var(--rk-warning, #a16207);\n stroke: var(--rk-warning, #a16207);\n stroke-width: 1.2;\n}\n\n.value {\n margin-left: 7px;\n font-size: 0.85em;\n font-weight: 600;\n color: var(--rk-ink-2, #52443c);\n font-variant-numeric: tabular-nums;\n}\n\n.count {\n margin-left: 4px;\n font-weight: 500;\n color: var(--rk-muted, #857166);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .star-wrap,\n .stars:not(.is-readonly) .star-wrap:hover {\n transition: none;\n transform: none;\n }\n}\n","import { Component, Event, EventEmitter, h, Host, Prop, State } from '@stencil/core';\n\n/**\n * A star rating that works as a read-only display or an interactive input.\n */\n@Component({\n tag: 'rk-rating',\n styleUrl: 'rk-rating.css',\n shadow: true,\n})\nexport class RkRating {\n /** Current rating. Supports halves when `readonly`. */\n @Prop({ mutable: true }) value = 0;\n\n /** Number of stars. */\n @Prop() max = 5;\n\n /** When true the stars are display-only and not focusable. */\n @Prop() readonly = false;\n\n /** Star size in pixels. */\n @Prop() size = 18;\n\n /** Accessible label for the group. */\n @Prop() label = 'Rating';\n\n /** Renders the numeric value next to the stars. */\n @Prop() showValue = false;\n\n /** Optional count of ratings, rendered as \"(24)\". */\n @Prop() count?: number;\n\n /** Emitted when the user picks a new rating. */\n @Event({ eventName: 'rkRatingChange' }) rkRatingChange!: EventEmitter<number>;\n\n @State() private hovered = 0;\n\n private select(next: number) {\n if (this.readonly) return;\n // Clicking the active star clears the rating, which is the usual affordance.\n const resolved = next === this.value ? 0 : next;\n this.value = resolved;\n this.rkRatingChange.emit(resolved);\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (this.readonly) return;\n const step = event.key === 'ArrowRight' || event.key === 'ArrowUp' ? 1 : event.key === 'ArrowLeft' || event.key === 'ArrowDown' ? -1 : 0;\n if (step === 0) return;\n event.preventDefault();\n const next = Math.min(this.max, Math.max(0, Math.round(this.value) + step));\n this.value = next;\n this.rkRatingChange.emit(next);\n };\n\n render() {\n const active = this.hovered || this.value;\n const stars = Array.from({ length: Math.max(1, Math.round(this.max)) }, (_, index) => index + 1);\n\n return (\n <Host style={{ '--rk-star-size': `${this.size}px` }}>\n <div\n class={{ stars: true, 'is-readonly': this.readonly }}\n part=\"stars\"\n role={this.readonly ? 'img' : 'slider'}\n aria-label={`${this.label}: ${this.value} out of ${this.max}`}\n aria-valuenow={this.readonly ? null : String(this.value)}\n aria-valuemin={this.readonly ? null : '0'}\n aria-valuemax={this.readonly ? null : String(this.max)}\n tabindex={this.readonly ? null : 0}\n onKeyDown={this.handleKeyDown}\n onMouseLeave={() => (this.hovered = 0)}\n >\n {stars.map(star => {\n // Fractional fill only matters in read-only display mode.\n const fill = this.readonly ? Math.min(1, Math.max(0, this.value - (star - 1))) : star <= active ? 1 : 0;\n\n return (\n <span\n class=\"star-wrap\"\n key={star}\n onMouseEnter={() => !this.readonly && (this.hovered = star)}\n onClick={() => this.select(star)}\n aria-hidden=\"true\"\n >\n <svg class=\"star\" viewBox=\"0 0 24 24\">\n <path\n class=\"star-bg\"\n d=\"M12 2.6l2.86 5.98 6.54.87-4.8 4.5 1.2 6.45L12 17.3l-5.8 3.1 1.2-6.45-4.8-4.5 6.54-.87z\"\n />\n <clipPath id={`clip-${star}`}>\n <rect x=\"0\" y=\"0\" width={24 * fill} height=\"24\" />\n </clipPath>\n <path\n class=\"star-fg\"\n clip-path={`url(#clip-${star})`}\n d=\"M12 2.6l2.86 5.98 6.54.87-4.8 4.5 1.2 6.45L12 17.3l-5.8 3.1 1.2-6.45-4.8-4.5 6.54-.87z\"\n />\n </svg>\n </span>\n );\n })}\n\n {this.showValue && (\n <span class=\"value\" part=\"value\">\n {this.value ? this.value.toFixed(1) : '—'}\n {typeof this.count === 'number' && <span class=\"count\">({this.count})</span>}\n </span>\n )}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"kEAAA,MAAMA,EAAc,IAAM,s9B,MCUbC,EAAQC,EAAA,MAAAD,UAAAE,EALrB,WAAAC,CAAAC,G,+GAO2BC,KAAAC,MAAQ,EAGzBD,KAAAE,IAAM,EAGNF,KAAAG,SAAW,MAGXH,KAAAI,KAAO,GAGPJ,KAAAK,MAAQ,SAGRL,KAAAM,UAAY,MAQHN,KAAAO,QAAU,EAUnBP,KAAAQ,cAAiBC,IACvB,GAAIT,KAAKG,SAAU,OACnB,MAAMO,EAAOD,EAAME,MAAQ,cAAgBF,EAAME,MAAQ,UAAY,EAAIF,EAAME,MAAQ,aAAeF,EAAME,MAAQ,aAAc,EAAK,EACvI,GAAID,IAAS,EAAG,OAChBD,EAAMG,iBACN,MAAMC,EAAOC,KAAKC,IAAIf,KAAKE,IAAKY,KAAKZ,IAAI,EAAGY,KAAKE,MAAMhB,KAAKC,OAASS,IACrEV,KAAKC,MAAQY,EACbb,KAAKiB,eAAeC,KAAKL,EAAK,CA6DjC,CA5ES,MAAAM,CAAON,GACb,GAAIb,KAAKG,SAAU,OAEnB,MAAMiB,EAAWP,IAASb,KAAKC,MAAQ,EAAIY,EAC3Cb,KAAKC,MAAQmB,EACbpB,KAAKiB,eAAeC,KAAKE,E,CAa3B,MAAAC,GACE,MAAMC,EAAStB,KAAKO,SAAWP,KAAKC,MACpC,MAAMsB,EAAQC,MAAMC,KAAK,CAAEC,OAAQZ,KAAKZ,IAAI,EAAGY,KAAKE,MAAMhB,KAAKE,QAAS,CAACyB,EAAGC,IAAUA,EAAQ,IAE9F,OACEC,EAACC,EAAI,CAAAnB,IAAA,2CAACoB,MAAO,CAAE,iBAAkB,GAAG/B,KAAKI,WACvCyB,EAAA,OAAAlB,IAAA,2CACEqB,MAAO,CAAET,MAAO,KAAM,cAAevB,KAAKG,UAC1C8B,KAAK,QACLC,KAAMlC,KAAKG,SAAW,MAAQ,SAAQ,aAC1B,GAAGH,KAAKK,UAAUL,KAAKC,gBAAgBD,KAAKE,MAAK,gBAC9CF,KAAKG,SAAW,KAAOgC,OAAOnC,KAAKC,OAAM,gBACzCD,KAAKG,SAAW,KAAO,IAAG,gBAC1BH,KAAKG,SAAW,KAAOgC,OAAOnC,KAAKE,KAClDkC,SAAUpC,KAAKG,SAAW,KAAO,EACjCkC,UAAWrC,KAAKQ,cAChB8B,aAAc,IAAOtC,KAAKO,QAAU,GAEnCgB,EAAMgB,KAAIC,IAET,MAAMC,EAAOzC,KAAKG,SAAWW,KAAKC,IAAI,EAAGD,KAAKZ,IAAI,EAAGF,KAAKC,OAASuC,EAAO,KAAOA,GAAQlB,EAAS,EAAI,EAEtG,OACEO,EAAA,QACEG,MAAM,YACNrB,IAAK6B,EACLE,aAAc,KAAO1C,KAAKG,WAAaH,KAAKO,QAAUiC,GACtDG,QAAS,IAAM3C,KAAKmB,OAAOqB,GAAK,cACpB,QAEZX,EAAA,OAAKG,MAAM,OAAOY,QAAQ,aACxBf,EAAA,QACEG,MAAM,UACNa,EAAE,2FAEJhB,EAAA,YAAUiB,GAAI,QAAQN,KACpBX,EAAA,QAAMkB,EAAE,IAAIC,EAAE,IAAIC,MAAO,GAAKR,EAAMS,OAAO,QAE7CrB,EAAA,QACEG,MAAM,UAAS,YACJ,aAAaQ,KACxBK,EAAE,4FAGD,IAIV7C,KAAKM,WACJuB,EAAA,QAAAlB,IAAA,2CAAMqB,MAAM,QAAQC,KAAK,SACtBjC,KAAKC,MAAQD,KAAKC,MAAMkD,QAAQ,GAAK,WAC9BnD,KAAKoD,QAAU,UAAYvB,EAAA,QAAAlB,IAAA,2CAAMqB,MAAM,SAAO,IAAGhC,KAAKoD,MAAc,O","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkRecipeCard extends Components.RkRecipeCard, HTMLElement {}
4
+ export const RkRecipeCard: {
5
+ prototype: RkRecipeCard;
6
+ new (): RkRecipeCard;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as e,H as t,c as a,h as r,t as i}from"./index.js";const o=()=>`:host{display:block;font-family:var(--rk-font);font-size:var(--rk-font-size, 15px);color:var(--rk-ink, #211a16);height:100%}.card{position:relative;display:flex;flex-direction:column;height:100%;background:var(--rk-surface, #fff);border:1px solid var(--rk-border, #ecdfd4);border-radius:var(--rk-radius-lg, 20px);overflow:hidden;box-shadow:var(--rk-shadow-sm);transition:transform var(--rk-transition), box-shadow var(--rk-transition), border-color var(--rk-transition)}.card:hover{transform:translateY(-3px);box-shadow:var(--rk-shadow);border-color:var(--rk-border-strong, #d9c6b8)}.media{position:relative;display:block;aspect-ratio:4 / 3;background:var(--rk-surface-2, #fdf5ef);overflow:hidden;text-decoration:none}.media img{width:100%;height:100%;object-fit:cover;display:block;transition:transform 420ms cubic-bezier(0.2, 0, 0.2, 1)}.card:hover .media img{transform:scale(1.045)}.media-fallback{position:absolute;inset:0;display:grid;place-items:center;font-size:2.6rem;opacity:0.5}.owned{position:absolute;left:10px;bottom:10px;padding:4px 10px;border-radius:var(--rk-radius-pill, 999px);background:var(--rk-accent, #0f766e);color:#fff;font-size:0.72em;font-weight:700;letter-spacing:0.03em;text-transform:uppercase}.fav{position:absolute;top:10px;right:10px;z-index:2;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;padding:0;border:0;border-radius:50%;background:rgba(255, 255, 255, 0.9);backdrop-filter:blur(6px);color:var(--rk-ink-2, #52443c);cursor:pointer;box-shadow:var(--rk-shadow-sm);transition:background var(--rk-transition), color var(--rk-transition), transform var(--rk-transition)}.fav svg{width:20px;height:20px;fill:none;transition:fill var(--rk-transition)}.fav:hover{transform:scale(1.08);color:var(--rk-primary, #d94f1b)}.fav:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.fav.is-on{color:var(--rk-primary, #d94f1b)}.fav.is-on svg{fill:currentColor}.body{display:flex;flex-direction:column;gap:7px;padding:15px 16px 0;flex:1 1 auto}.title{margin:0;font-family:var(--rk-font-display, serif);font-size:1.12em;font-weight:650;line-height:1.28;letter-spacing:-0.01em}.title a{color:inherit;text-decoration:none;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.title a:hover{color:var(--rk-primary, #d94f1b)}.title a:focus-visible{outline:none;border-radius:4px;box-shadow:var(--rk-focus-ring)}.meta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px;margin:0;font-size:0.83em;color:var(--rk-muted, #857166)}.meta-item{position:relative;white-space:nowrap}.meta-item+.meta-item::before{content:'';position:absolute;left:-8px;top:50%;width:3px;height:3px;border-radius:50%;background:currentColor;opacity:0.55;transform:translateY(-50%)}.extra{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:3px}.footer{display:flex;align-items:center;gap:8px;padding:14px 16px;margin-top:12px;border-top:1px solid var(--rk-border, #ecdfd4)}.footer ::slotted(*){flex:1 1 auto}.extra.is-empty,.footer.is-empty{display:none}.card:has(.footer.is-empty) .body{padding-bottom:16px}.card.is-compact{flex-direction:row;align-items:stretch;border-radius:var(--rk-radius, 14px)}.card.is-compact:hover{transform:none}.card.is-compact .media{flex:0 0 96px;aspect-ratio:1 / 1}.card.is-compact .body{padding:12px 14px;gap:4px;justify-content:center}.card.is-compact .title{font-size:1em}.card.is-compact .fav{width:32px;height:32px;top:8px;right:8px}.card.is-compact .fav svg{width:17px;height:17px}.card.is-compact .footer{margin-top:0;border-top:0;border-left:1px solid var(--rk-border, #ecdfd4);padding:12px}.card.is-compact .owned{display:none}@media (prefers-reduced-motion: reduce){.card,.card:hover,.media img,.card:hover .media img,.fav{transition:none;transform:none}}`;const s=e(class e extends t{constructor(e){super();if(e!==false){this.__registerHost()}this.__attachShadow();this.rkCardSelect=a(this,"rkCardSelect");this.rkFavoriteToggle=a(this,"rkFavoriteToggle");this.name="";this.favorite=false;this.origin="api";this.compact=false;this.hideFavorite=false;this.imageFailed=false;this.hasExtra=false;this.hasActions=false;this.syncSlots=()=>{const e=Array.from(this.host.children);this.hasActions=e.some((e=>e.getAttribute("slot")==="actions"));this.hasExtra=e.some((e=>!e.hasAttribute("slot")))||Array.from(this.host.childNodes).some((e=>e.nodeType===Node.TEXT_NODE&&(e.textContent??"").trim()!==""))};this.handleSelect=e=>{if(e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||e.button!==0){return}e.preventDefault();this.rkCardSelect.emit(this.detail)};this.handleFavorite=e=>{e.preventDefault();e.stopPropagation();this.rkFavoriteToggle.emit({...this.detail,favorite:!this.favorite})}}componentWillLoad(){this.syncSlots()}get detail(){return{recipeId:this.recipeId,name:this.name,origin:this.origin}}render(){const e=this.image&&!this.imageFailed;const t=this.href??`#${this.recipeId}`;return r("article",{key:"abc3f8de736b74b1446ced7f2745c5a60b489c24",class:{card:true,"is-compact":this.compact},part:"card"},r("a",{key:"c401e8d99a43bbc5b4a67f1b79d02a4afd17fefc",class:"media",part:"media",href:t,tabindex:-1,"aria-hidden":"true",onClick:this.handleSelect},e?r("img",{src:this.image,alt:"",loading:"lazy",decoding:"async",onError:()=>this.imageFailed=true}):r("span",{class:"media-fallback","aria-hidden":"true"},"🍲"),this.origin==="custom"&&r("span",{key:"d73c90426f8727a313d047db677a92184e57d794",class:"owned",part:"owned-badge"},"Yours")),!this.hideFavorite&&r("button",{key:"2f8cbaec4403219b0d39529758ef52bf8cb1fb7a",class:{fav:true,"is-on":this.favorite},part:"favorite-button",type:"button",onClick:this.handleFavorite,"aria-pressed":String(this.favorite),"aria-label":this.favorite?`Remove ${this.name} from favorites`:`Add ${this.name} to favorites`,title:this.favorite?"Remove from favorites":"Add to favorites"},r("svg",{key:"5766d053203efbf14be2ef9c6f6e1e7d8fa72552",viewBox:"0 0 24 24",stroke:"currentColor","stroke-width":"1.9","stroke-linejoin":"round","aria-hidden":"true"},r("path",{key:"1eebb81f40253f26b3ea021dd08cd6fd67b6e2ea",d:"M12 20.5 4.6 13.3a4.7 4.7 0 0 1 0-6.7 4.7 4.7 0 0 1 6.7 0l.7.7.7-.7a4.7 4.7 0 0 1 6.7 0 4.7 4.7 0 0 1 0 6.7Z"}))),r("div",{key:"0dd0feccc789b188cecc42d920e44e39556a9134",class:"body",part:"body"},r("h3",{key:"29739cf1838d2a2827985104da23e62498c00a00",class:"title",part:"title"},r("a",{key:"d42fa3f306da565f8a04179a699fc7b6092839d6",href:t,onClick:this.handleSelect},this.name)),r("p",{key:"3a16c25552fab648854e3923d6f0a389f916b07f",class:"meta",part:"meta"},this.category&&r("span",{key:"ea8788f2772055734cc6740fc073c48061ff7b1c",class:"meta-item"},this.category),this.area&&r("span",{key:"b54bba9cd55cec0296a483efa8a865c8b50dab03",class:"meta-item"},this.area),this.minutes>0&&r("span",{key:"11c08808645b3dbd942d5374edf92bcd18af85a1",class:"meta-item"},this.minutes," min"),this.servings>0&&r("span",{key:"28064d47688d06897a3b46ff039d66483e280803",class:"meta-item"},"Serves ",this.servings)),r("div",{key:"3bf5b7ad91730f16697854287d3853b371d27cf4",class:{extra:true,"is-empty":!this.hasExtra},part:"extra"},r("slot",{key:"1dfe7c29f1d350e85c4cd8122f6fe7e07c60f56f",onSlotchange:this.syncSlots}))),r("footer",{key:"56e115b1e6c46fc5de7a8df9ea005011787ecd51",class:{footer:true,"is-empty":!this.hasActions},part:"footer"},r("slot",{key:"d07e312d8486a7b761856f5137f24ab95a98c582",name:"actions",onSlotchange:this.syncSlots})))}get host(){return this}static get style(){return o()}},[257,"rk-recipe-card",{recipeId:[1,"recipe-id"],name:[1],image:[1],category:[1],area:[1],minutes:[2],servings:[2],favorite:[4],origin:[1],href:[1],compact:[4],hideFavorite:[4,"hide-favorite"],imageFailed:[32],hasExtra:[32],hasActions:[32]}]);function d(){if(typeof customElements==="undefined"){return}const e=["rk-recipe-card"];e.forEach((e=>{switch(e){case"rk-recipe-card":if(!customElements.get(i(e))){customElements.define(i(e),s)}break}}))}d();const n=s;const c=d;export{n as RkRecipeCard,c as defineCustomElement};
2
+ //# sourceMappingURL=rk-recipe-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkRecipeCardCss","RkRecipeCard","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","name","favorite","origin","compact","hideFavorite","imageFailed","hasExtra","hasActions","syncSlots","elements","Array","from","host","children","some","node","getAttribute","hasAttribute","childNodes","nodeType","Node","TEXT_NODE","textContent","trim","handleSelect","event","metaKey","ctrlKey","shiftKey","altKey","button","preventDefault","rkCardSelect","emit","detail","handleFavorite","stopPropagation","rkFavoriteToggle","componentWillLoad","recipeId","render","showImage","image","href","h","key","class","card","part","tabindex","onClick","src","alt","loading","decoding","onError","fav","type","String","title","viewBox","stroke","d","category","area","minutes","servings","extra","onSlotchange","footer"],"sources":["src/components/rk-recipe-card/rk-recipe-card.css?tag=rk-recipe-card&encapsulation=shadow","src/components/rk-recipe-card/rk-recipe-card.tsx"],"sourcesContent":[":host {\n display: block;\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n color: var(--rk-ink, #211a16);\n height: 100%;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--rk-surface, #fff);\n border: 1px solid var(--rk-border, #ecdfd4);\n border-radius: var(--rk-radius-lg, 20px);\n overflow: hidden;\n box-shadow: var(--rk-shadow-sm);\n transition: transform var(--rk-transition), box-shadow var(--rk-transition), border-color var(--rk-transition);\n}\n\n.card:hover {\n transform: translateY(-3px);\n box-shadow: var(--rk-shadow);\n border-color: var(--rk-border-strong, #d9c6b8);\n}\n\n/* ---------- media ---------- */\n\n.media {\n position: relative;\n display: block;\n aspect-ratio: 4 / 3;\n background: var(--rk-surface-2, #fdf5ef);\n overflow: hidden;\n text-decoration: none;\n}\n\n.media img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n transition: transform 420ms cubic-bezier(0.2, 0, 0.2, 1);\n}\n\n.card:hover .media img {\n transform: scale(1.045);\n}\n\n.media-fallback {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n font-size: 2.6rem;\n opacity: 0.5;\n}\n\n.owned {\n position: absolute;\n left: 10px;\n bottom: 10px;\n padding: 4px 10px;\n border-radius: var(--rk-radius-pill, 999px);\n background: var(--rk-accent, #0f766e);\n color: #fff;\n font-size: 0.72em;\n font-weight: 700;\n letter-spacing: 0.03em;\n text-transform: uppercase;\n}\n\n/* ---------- favorite ---------- */\n\n.fav {\n position: absolute;\n top: 10px;\n right: 10px;\n z-index: 2;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 38px;\n height: 38px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.9);\n backdrop-filter: blur(6px);\n color: var(--rk-ink-2, #52443c);\n cursor: pointer;\n box-shadow: var(--rk-shadow-sm);\n transition: background var(--rk-transition), color var(--rk-transition), transform var(--rk-transition);\n}\n\n.fav svg {\n width: 20px;\n height: 20px;\n fill: none;\n transition: fill var(--rk-transition);\n}\n\n.fav:hover {\n transform: scale(1.08);\n color: var(--rk-primary, #d94f1b);\n}\n\n.fav:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.fav.is-on {\n color: var(--rk-primary, #d94f1b);\n}\n\n.fav.is-on svg {\n fill: currentColor;\n}\n\n/* ---------- body ---------- */\n\n.body {\n display: flex;\n flex-direction: column;\n gap: 7px;\n padding: 15px 16px 0;\n flex: 1 1 auto;\n}\n\n.title {\n margin: 0;\n font-family: var(--rk-font-display, serif);\n font-size: 1.12em;\n font-weight: 650;\n line-height: 1.28;\n letter-spacing: -0.01em;\n}\n\n.title a {\n color: inherit;\n text-decoration: none;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.title a:hover {\n color: var(--rk-primary, #d94f1b);\n}\n\n.title a:focus-visible {\n outline: none;\n border-radius: 4px;\n box-shadow: var(--rk-focus-ring);\n}\n\n.meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px 14px;\n margin: 0;\n font-size: 0.83em;\n color: var(--rk-muted, #857166);\n}\n\n.meta-item {\n position: relative;\n white-space: nowrap;\n}\n\n.meta-item + .meta-item::before {\n content: '';\n position: absolute;\n left: -8px;\n top: 50%;\n width: 3px;\n height: 3px;\n border-radius: 50%;\n background: currentColor;\n opacity: 0.55;\n transform: translateY(-50%);\n}\n\n.extra {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 3px;\n}\n\n/* ---------- footer ---------- */\n\n.footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 14px 16px;\n margin-top: 12px;\n border-top: 1px solid var(--rk-border, #ecdfd4);\n}\n\n.footer ::slotted(*) {\n flex: 1 1 auto;\n}\n\n.extra.is-empty,\n.footer.is-empty {\n display: none;\n}\n\n/* Without a footer the body has to supply its own bottom padding. */\n.card:has(.footer.is-empty) .body {\n padding-bottom: 16px;\n}\n\n/* ---------- compact variant ---------- */\n\n.card.is-compact {\n flex-direction: row;\n align-items: stretch;\n border-radius: var(--rk-radius, 14px);\n}\n\n.card.is-compact:hover {\n transform: none;\n}\n\n.card.is-compact .media {\n flex: 0 0 96px;\n aspect-ratio: 1 / 1;\n}\n\n.card.is-compact .body {\n padding: 12px 14px;\n gap: 4px;\n justify-content: center;\n}\n\n.card.is-compact .title {\n font-size: 1em;\n}\n\n.card.is-compact .fav {\n width: 32px;\n height: 32px;\n top: 8px;\n right: 8px;\n}\n\n.card.is-compact .fav svg {\n width: 17px;\n height: 17px;\n}\n\n.card.is-compact .footer {\n margin-top: 0;\n border-top: 0;\n border-left: 1px solid var(--rk-border, #ecdfd4);\n padding: 12px;\n}\n\n.card.is-compact .owned {\n display: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .card,\n .card:hover,\n .media img,\n .card:hover .media img,\n .fav {\n transition: none;\n transform: none;\n }\n}\n","import { Component, Element, Event, EventEmitter, h, Prop, State } from '@stencil/core';\n\nexport interface RkRecipeCardSelectDetail {\n recipeId: string;\n name: string;\n origin: 'api' | 'custom';\n}\n\nexport interface RkFavoriteToggleDetail {\n recipeId: string;\n name: string;\n origin: 'api' | 'custom';\n /** The state the host app should move *to*. */\n favorite: boolean;\n}\n\n/**\n * The primary recipe tile used across discovery, favorites and search results.\n *\n * All data arrives as individual primitive properties rather than one object\n * prop, so the component works with plain HTML attributes in any framework.\n *\n * @slot - Extra metadata rendered under the title (badges, tags, ratings).\n * @slot actions - Buttons rendered in the card footer (e.g. \"Add to plan\").\n */\n@Component({\n tag: 'rk-recipe-card',\n styleUrl: 'rk-recipe-card.css',\n shadow: true,\n})\nexport class RkRecipeCard {\n @Element() host!: HTMLElement;\n\n /** Stable identifier echoed back in every event payload. */\n @Prop() recipeId!: string;\n\n /** Recipe title. */\n @Prop() name = '';\n\n /** Thumbnail URL. */\n @Prop() image?: string;\n\n /** Category, e.g. \"Dessert\". */\n @Prop() category?: string;\n\n /** Cuisine / region, e.g. \"Italian\". */\n @Prop() area?: string;\n\n /** Total time in minutes. Hidden when omitted. */\n @Prop() minutes?: number;\n\n /** Number of servings. Hidden when omitted. */\n @Prop() servings?: number;\n\n /** Whether this recipe is currently favorited. */\n @Prop() favorite = false;\n\n /** `custom` recipes are user-authored and get an \"Owned\" badge. */\n @Prop() origin: 'api' | 'custom' = 'api';\n\n /** Real href used for accessibility, SEO and middle-click / open-in-new-tab. */\n @Prop() href?: string;\n\n /** Renders a compact horizontal layout, for dense lists and the planner. */\n @Prop() compact = false;\n\n /** Hides the favorite button entirely (e.g. inside the planner). */\n @Prop() hideFavorite = false;\n\n /** Emitted on primary activation. The host app performs the navigation. */\n @Event({ eventName: 'rkCardSelect' }) rkCardSelect!: EventEmitter<RkRecipeCardSelectDetail>;\n\n /** Emitted when the favorite button is pressed. */\n @Event({ eventName: 'rkFavoriteToggle' }) rkFavoriteToggle!: EventEmitter<RkFavoriteToggleDetail>;\n\n @State() private imageFailed = false;\n @State() private hasExtra = false;\n @State() private hasActions = false;\n\n componentWillLoad() {\n this.syncSlots();\n }\n\n /**\n * Slot content is optional, and an empty wrapper would still paint padding and\n * a border. Tracking what was actually projected lets the card collapse those\n * regions instead. Re-run on `slotchange` so framework-driven updates count.\n */\n private syncSlots = () => {\n const elements = Array.from(this.host.children);\n this.hasActions = elements.some(node => node.getAttribute('slot') === 'actions');\n this.hasExtra =\n elements.some(node => !node.hasAttribute('slot')) ||\n Array.from(this.host.childNodes).some(node => node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim() !== '');\n };\n\n private get detail(): RkRecipeCardSelectDetail {\n return { recipeId: this.recipeId, name: this.name, origin: this.origin };\n }\n\n private handleSelect = (event: MouseEvent) => {\n // Let the browser handle modified clicks so \"open in new tab\" keeps working.\n if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {\n return;\n }\n event.preventDefault();\n this.rkCardSelect.emit(this.detail);\n };\n\n private handleFavorite = (event: MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n this.rkFavoriteToggle.emit({ ...this.detail, favorite: !this.favorite });\n };\n\n render() {\n const showImage = this.image && !this.imageFailed;\n const href = this.href ?? `#${this.recipeId}`;\n\n return (\n <article class={{ card: true, 'is-compact': this.compact }} part=\"card\">\n <a class=\"media\" part=\"media\" href={href} tabindex={-1} aria-hidden=\"true\" onClick={this.handleSelect}>\n {showImage ? (\n <img src={this.image} alt=\"\" loading=\"lazy\" decoding=\"async\" onError={() => (this.imageFailed = true)} />\n ) : (\n <span class=\"media-fallback\" aria-hidden=\"true\">\n 🍲\n </span>\n )}\n\n {this.origin === 'custom' && (\n <span class=\"owned\" part=\"owned-badge\">\n Yours\n </span>\n )}\n </a>\n\n {!this.hideFavorite && (\n <button\n class={{ fav: true, 'is-on': this.favorite }}\n part=\"favorite-button\"\n type=\"button\"\n onClick={this.handleFavorite}\n aria-pressed={String(this.favorite)}\n aria-label={this.favorite ? `Remove ${this.name} from favorites` : `Add ${this.name} to favorites`}\n title={this.favorite ? 'Remove from favorites' : 'Add to favorites'}\n >\n <svg viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"1.9\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M12 20.5 4.6 13.3a4.7 4.7 0 0 1 0-6.7 4.7 4.7 0 0 1 6.7 0l.7.7.7-.7a4.7 4.7 0 0 1 6.7 0 4.7 4.7 0 0 1 0 6.7Z\" />\n </svg>\n </button>\n )}\n\n <div class=\"body\" part=\"body\">\n <h3 class=\"title\" part=\"title\">\n <a href={href} onClick={this.handleSelect}>\n {this.name}\n </a>\n </h3>\n\n <p class=\"meta\" part=\"meta\">\n {this.category && <span class=\"meta-item\">{this.category}</span>}\n {this.area && <span class=\"meta-item\">{this.area}</span>}\n {this.minutes > 0 && <span class=\"meta-item\">{this.minutes} min</span>}\n {this.servings > 0 && <span class=\"meta-item\">Serves {this.servings}</span>}\n </p>\n\n <div class={{ extra: true, 'is-empty': !this.hasExtra }} part=\"extra\">\n <slot onSlotchange={this.syncSlots} />\n </div>\n </div>\n\n <footer class={{ footer: true, 'is-empty': !this.hasActions }} part=\"footer\">\n <slot name=\"actions\" onSlotchange={this.syncSlots} />\n </footer>\n </article>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkSearchBar extends Components.RkSearchBar, HTMLElement {}
4
+ export const RkSearchBar: {
5
+ prototype: RkSearchBar;
6
+ new (): RkSearchBar;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as e,H as a,c as t,h as r,a as i,t as s}from"./index.js";const n=()=>`:host{display:block;font-family:var(--rk-font);font-size:var(--rk-font-size, 15px);color:var(--rk-ink, #211a16)}.shell{display:flex;align-items:center;gap:10px;padding:0 10px 0 14px;min-height:52px;background:var(--rk-surface, #fff);border:1px solid var(--rk-border, #ecdfd4);border-radius:var(--rk-radius-pill, 999px);box-shadow:var(--rk-shadow-sm);transition:border-color var(--rk-transition), box-shadow var(--rk-transition)}.shell.is-focused{border-color:var(--rk-primary, #d94f1b);box-shadow:var(--rk-focus-ring)}.shell.is-disabled{opacity:0.6;cursor:not-allowed}.icon{display:inline-flex;flex:0 0 auto;color:var(--rk-muted, #857166)}.icon svg{width:20px;height:20px}.input{flex:1 1 auto;min-width:0;border:0;outline:none;background:transparent;font:inherit;color:inherit;padding:14px 0;appearance:none}.input::placeholder{color:var(--rk-muted, #857166);opacity:0.9}.input::-webkit-search-cancel-button,.input::-webkit-search-decoration{appearance:none;display:none}.clear{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:30px;height:30px;padding:0;border:0;border-radius:50%;background:var(--rk-surface-2, #fdf5ef);color:var(--rk-ink-2, #52443c);cursor:pointer;transition:background var(--rk-transition), color var(--rk-transition)}.clear:hover{background:var(--rk-primary-soft, #fdeee6);color:var(--rk-primary, #d94f1b)}.clear:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.clear svg{width:15px;height:15px}.spinner{flex:0 0 auto;width:18px;height:18px;border-radius:50%;border:2px solid var(--rk-border-strong, #d9c6b8);border-top-color:var(--rk-primary, #d94f1b);animation:rk-spin 700ms linear infinite}@keyframes rk-spin{to{transform:rotate(360deg)}}.actions{display:contents}.actions ::slotted(*){flex:0 0 auto}.hint{margin:8px 0 0;padding-left:16px;font-size:0.82em;color:var(--rk-muted, #857166)}@media (prefers-reduced-motion: reduce){.spinner{animation-duration:2s}.shell,.clear{transition:none}}`;const o=e(class e extends a{constructor(e){super();if(e!==false){this.__registerHost()}this.__attachShadow();this.rkSearch=t(this,"rkSearch");this.rkClear=t(this,"rkClear");this.value="";this.placeholder="Search recipes, ingredients, cuisines…";this.label="Search recipes";this.debounce=350;this.disabled=false;this.loading=false;this.focused=false;this.handleInput=e=>{const a=e.target.value;this.value=a;clearTimeout(this.timer);this.timer=setTimeout((()=>this.emit(a)),Math.max(0,this.debounce))};this.handleKeyDown=e=>{if(e.key==="Enter"){e.preventDefault();this.emit(this.value)}else if(e.key==="Escape"&&this.value){e.preventDefault();this.handleClear()}};this.handleClear=()=>{clearTimeout(this.timer);this.value="";if(this.inputEl)this.inputEl.value="";this.rkClear.emit();this.rkSearch.emit("");this.inputEl?.focus()}}onValueChange(e,a){if(this.inputEl&&this.inputEl.value!==e&&e!==a){this.inputEl.value=e??""}}disconnectedCallback(){clearTimeout(this.timer)}async setFocus(){this.inputEl?.focus()}emit(e){clearTimeout(this.timer);this.rkSearch.emit(e.trim())}render(){const e=(this.value??"").length>0;return r(i,{key:"cf58faf063a6c13bada8f5713f0dcbb582962577"},r("div",{key:"13bdb192a7cb4fd699ffae8a9f67fba3e1a68c16",class:{shell:true,"is-focused":this.focused,"is-disabled":this.disabled},part:"shell"},r("span",{key:"fe65bb803f4e3c01c1bf1eab66ab70658256820e",class:"icon","aria-hidden":"true"},r("svg",{key:"a20ca316e086189ad00f8e9fed05cfa21c43fa10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round"},r("circle",{key:"8298c51dc269224356a1e3248838e2ff8c20aab3",cx:"11",cy:"11",r:"7"}),r("path",{key:"92acd9c5a363ad4a9e9f14cbcf6b4ff86aae2bf2",d:"m20 20-3.5-3.5"}))),r("input",{key:"5fef80ea1e552630361556381dd09b62874334ca",ref:e=>this.inputEl=e,class:"input",part:"input",type:"search",value:this.value,placeholder:this.placeholder,"aria-label":this.label,"aria-busy":this.loading?"true":"false",disabled:this.disabled,autocomplete:"off",autocapitalize:"off",spellcheck:false,enterkeyhint:"search",onInput:this.handleInput,onKeyDown:this.handleKeyDown,onFocus:()=>this.focused=true,onBlur:()=>this.focused=false}),this.loading&&r("span",{key:"17c0e5483cc3bea79642192c6cb8548f32071f02",class:"spinner",part:"spinner","aria-hidden":"true"}),e&&!this.loading&&r("button",{key:"7df966f93f1de6a1d3a380c4856f235a671521ad",class:"clear",part:"clear",type:"button",onClick:this.handleClear,"aria-label":"Clear search",disabled:this.disabled},r("svg",{key:"29457188a630e71e4c29f93939edbcb28862cade",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","aria-hidden":"true"},r("path",{key:"64406c87eaaa582151fdf5d1ee7929a6f311cc4c",d:"M6 6l12 12M18 6 6 18"}))),r("span",{key:"7abf5bd0cdb2d15b7143491c5de5216df872deff",class:"actions",part:"actions"},r("slot",{key:"09fa60e54e72af6c9e7187f3406a11e80d5a3004",name:"actions"}))),this.hint&&r("p",{key:"1dd826505bcfc2cb5b7712adc18e7e29dc814f2b",class:"hint",part:"hint"},this.hint))}static get watchers(){return{value:[{onValueChange:0}]}}static get style(){return n()}},[257,"rk-search-bar",{value:[1025],placeholder:[1],label:[1],debounce:[2],disabled:[4],loading:[4],hint:[1],focused:[32],setFocus:[64]},undefined,{value:[{onValueChange:0}]}]);function c(){if(typeof customElements==="undefined"){return}const e=["rk-search-bar"];e.forEach((e=>{switch(e){case"rk-search-bar":if(!customElements.get(s(e))){customElements.define(s(e),o)}break}}))}c();const d=o;const l=c;export{d as RkSearchBar,l as defineCustomElement};
2
+ //# sourceMappingURL=rk-search-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkSearchBarCss","RkSearchBar","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","value","placeholder","label","debounce","disabled","loading","focused","handleInput","event","next","target","clearTimeout","timer","setTimeout","emit","Math","max","handleKeyDown","key","preventDefault","handleClear","inputEl","rkClear","rkSearch","focus","onValueChange","prev","disconnectedCallback","setFocus","query","trim","render","hasValue","length","h","Host","class","shell","part","viewBox","fill","stroke","cx","cy","r","d","ref","el","type","autocomplete","autocapitalize","spellcheck","enterkeyhint","onInput","onKeyDown","onFocus","onBlur","onClick","name","hint"],"sources":["src/components/rk-search-bar/rk-search-bar.css?tag=rk-search-bar&encapsulation=shadow","src/components/rk-search-bar/rk-search-bar.tsx"],"sourcesContent":[":host {\n display: block;\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n color: var(--rk-ink, #211a16);\n}\n\n.shell {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 0 10px 0 14px;\n min-height: 52px;\n background: var(--rk-surface, #fff);\n border: 1px solid var(--rk-border, #ecdfd4);\n border-radius: var(--rk-radius-pill, 999px);\n box-shadow: var(--rk-shadow-sm);\n transition: border-color var(--rk-transition), box-shadow var(--rk-transition);\n}\n\n.shell.is-focused {\n border-color: var(--rk-primary, #d94f1b);\n box-shadow: var(--rk-focus-ring);\n}\n\n.shell.is-disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.icon {\n display: inline-flex;\n flex: 0 0 auto;\n color: var(--rk-muted, #857166);\n}\n\n.icon svg {\n width: 20px;\n height: 20px;\n}\n\n.input {\n flex: 1 1 auto;\n min-width: 0;\n border: 0;\n outline: none;\n background: transparent;\n font: inherit;\n color: inherit;\n padding: 14px 0;\n appearance: none;\n}\n\n.input::placeholder {\n color: var(--rk-muted, #857166);\n opacity: 0.9;\n}\n\n/* Hide the native WebKit clear affordance — we render our own. */\n.input::-webkit-search-cancel-button,\n.input::-webkit-search-decoration {\n appearance: none;\n display: none;\n}\n\n.clear {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 30px;\n height: 30px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n background: var(--rk-surface-2, #fdf5ef);\n color: var(--rk-ink-2, #52443c);\n cursor: pointer;\n transition: background var(--rk-transition), color var(--rk-transition);\n}\n\n.clear:hover {\n background: var(--rk-primary-soft, #fdeee6);\n color: var(--rk-primary, #d94f1b);\n}\n\n.clear:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.clear svg {\n width: 15px;\n height: 15px;\n}\n\n.spinner {\n flex: 0 0 auto;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n border: 2px solid var(--rk-border-strong, #d9c6b8);\n border-top-color: var(--rk-primary, #d94f1b);\n animation: rk-spin 700ms linear infinite;\n}\n\n@keyframes rk-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/*\n * `display: contents` promotes slotted controls to flex items of `.shell`, so an\n * empty `actions` slot leaves no stray box (and no stray gap) behind.\n */\n.actions {\n display: contents;\n}\n\n.actions ::slotted(*) {\n flex: 0 0 auto;\n}\n\n.hint {\n margin: 8px 0 0;\n padding-left: 16px;\n font-size: 0.82em;\n color: var(--rk-muted, #857166);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .spinner {\n animation-duration: 2s;\n }\n\n .shell,\n .clear {\n transition: none;\n }\n}\n","import { Component, Event, EventEmitter, h, Host, Method, Prop, State, Watch } from '@stencil/core';\n\n/**\n * A debounced search input with a clear affordance and a slot for extra controls.\n *\n * @slot actions - Rendered to the right of the input, inside the field shell.\n * Useful for a \"filters\" toggle or a sort control.\n */\n@Component({\n tag: 'rk-search-bar',\n styleUrl: 'rk-search-bar.css',\n shadow: true,\n})\nexport class RkSearchBar {\n /** Current text in the field. Two-way: updated as the user types. */\n @Prop({ mutable: true }) value = '';\n\n /** Placeholder shown when the field is empty. */\n @Prop() placeholder = 'Search recipes, ingredients, cuisines…';\n\n /** Accessible label for the input. */\n @Prop() label = 'Search recipes';\n\n /** Milliseconds to wait after the last keystroke before emitting `rkSearch`. */\n @Prop() debounce = 350;\n\n /** Disables the whole control. */\n @Prop() disabled = false;\n\n /** Shows a busy indicator (e.g. while the app is fetching results). */\n @Prop() loading = false;\n\n /** Optional helper text rendered under the field. */\n @Prop() hint?: string;\n\n /** Emitted with the (trimmed) query after the debounce window, or on submit. */\n @Event({ eventName: 'rkSearch' }) rkSearch!: EventEmitter<string>;\n\n /** Emitted when the user clears the field with the clear button or Escape. */\n @Event({ eventName: 'rkClear' }) rkClear!: EventEmitter<void>;\n\n @State() private focused = false;\n\n private inputEl?: HTMLInputElement;\n private timer?: ReturnType<typeof setTimeout>;\n\n @Watch('value')\n protected onValueChange(next: string, prev: string) {\n // Keep the DOM input in sync when the value is driven from the outside.\n if (this.inputEl && this.inputEl.value !== next && next !== prev) {\n this.inputEl.value = next ?? '';\n }\n }\n\n disconnectedCallback() {\n clearTimeout(this.timer);\n }\n\n /** Programmatically focus the input. */\n @Method()\n async setFocus() {\n this.inputEl?.focus();\n }\n\n private emit(query: string) {\n clearTimeout(this.timer);\n this.rkSearch.emit(query.trim());\n }\n\n private handleInput = (event: Event) => {\n const next = (event.target as HTMLInputElement).value;\n this.value = next;\n clearTimeout(this.timer);\n this.timer = setTimeout(() => this.emit(next), Math.max(0, this.debounce));\n };\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter') {\n event.preventDefault();\n this.emit(this.value);\n } else if (event.key === 'Escape' && this.value) {\n event.preventDefault();\n this.handleClear();\n }\n };\n\n private handleClear = () => {\n clearTimeout(this.timer);\n this.value = '';\n if (this.inputEl) this.inputEl.value = '';\n this.rkClear.emit();\n this.rkSearch.emit('');\n this.inputEl?.focus();\n };\n\n render() {\n const hasValue = (this.value ?? '').length > 0;\n\n return (\n <Host>\n <div class={{ shell: true, 'is-focused': this.focused, 'is-disabled': this.disabled }} part=\"shell\">\n <span class=\"icon\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"m20 20-3.5-3.5\" />\n </svg>\n </span>\n\n <input\n ref={el => (this.inputEl = el)}\n class=\"input\"\n part=\"input\"\n type=\"search\"\n value={this.value}\n placeholder={this.placeholder}\n aria-label={this.label}\n aria-busy={this.loading ? 'true' : 'false'}\n disabled={this.disabled}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n spellcheck={false}\n enterkeyhint=\"search\"\n onInput={this.handleInput}\n onKeyDown={this.handleKeyDown}\n onFocus={() => (this.focused = true)}\n onBlur={() => (this.focused = false)}\n />\n\n {this.loading && <span class=\"spinner\" part=\"spinner\" aria-hidden=\"true\" />}\n\n {hasValue && !this.loading && (\n <button class=\"clear\" part=\"clear\" type=\"button\" onClick={this.handleClear} aria-label=\"Clear search\" disabled={this.disabled}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6 6 18\" />\n </svg>\n </button>\n )}\n\n <span class=\"actions\" part=\"actions\">\n <slot name=\"actions\" />\n </span>\n </div>\n\n {this.hint && (\n <p class=\"hint\" part=\"hint\">\n {this.hint}\n </p>\n )}\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkSegmentedControl extends Components.RkSegmentedControl, HTMLElement {}
4
+ export const RkSegmentedControl: {
5
+ prototype: RkSegmentedControl;
6
+ new (): RkSegmentedControl;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as t,H as e,c as s,h as r,t as n}from"./index.js";const i=()=>`:host{display:inline-block;font-family:var(--rk-font);font-size:var(--rk-font-size, 15px);max-width:100%}.group{display:inline-flex;align-items:center;gap:2px;padding:3px;background:var(--rk-surface-2, #fdf5ef);border:1px solid var(--rk-border, #ecdfd4);border-radius:var(--rk-radius-pill, 999px);max-width:100%;overflow-x:auto;scrollbar-width:none}.group::-webkit-scrollbar{display:none}.group.is-stretch{display:flex;width:100%}.segment{display:inline-flex;align-items:center;gap:6px;flex:0 0 auto;padding:8px 16px;border:0;border-radius:var(--rk-radius-pill, 999px);background:transparent;color:var(--rk-ink-2, #52443c);font:inherit;font-size:0.88em;font-weight:550;line-height:1;white-space:nowrap;cursor:pointer;transition:background var(--rk-transition), color var(--rk-transition), box-shadow var(--rk-transition)}.group.is-stretch .segment{flex:1 1 0;justify-content:center}.segment:hover:not(:disabled):not(.is-selected){background:rgba(0, 0, 0, 0.04);color:var(--rk-ink, #211a16)}.segment:focus-visible{outline:none;box-shadow:var(--rk-focus-ring)}.segment.is-selected{background:var(--rk-surface, #fff);color:var(--rk-ink, #211a16);box-shadow:var(--rk-shadow-sm);font-weight:650}.segment:disabled{opacity:0.45;cursor:not-allowed}.count{font-size:0.85em;font-weight:650;color:var(--rk-muted, #857166);font-variant-numeric:tabular-nums}.segment.is-selected .count{color:var(--rk-primary, #d94f1b)}@media (prefers-reduced-motion: reduce){.segment{transition:none}}`;const o=t(class t extends e{constructor(t){super();if(t!==false){this.__registerHost()}this.__attachShadow();this.rkSegmentChange=s(this,"rkSegmentChange");this.options=[];this.label="View options";this.stretch=false;this.parsed=[];this.handleKeyDown=(t,e)=>{const s=t.key==="ArrowRight"?1:t.key==="ArrowLeft"?-1:0;if(s===0)return;t.preventDefault();const r=this.parsed.filter((t=>!t.disabled));if(r.length===0)return;const n=r.indexOf(this.parsed[e]);const i=r[(n+s+r.length)%r.length];this.select(i)}}onOptionsChange(){this.parseOptions()}componentWillLoad(){this.parseOptions()}parseOptions(){if(Array.isArray(this.options)){this.parsed=this.options;return}if(typeof this.options==="string"&&this.options.trim()){try{const t=JSON.parse(this.options);this.parsed=Array.isArray(t)?t:[]}catch{console.warn("[rk-segmented-control] `options` is not valid JSON:",this.options);this.parsed=[]}return}this.parsed=[]}select(t){if(t.disabled||t.value===this.value)return;this.value=t.value;this.rkSegmentChange.emit(t.value)}render(){return r("div",{key:"e2b6eec632ebe51b9f259c60b174126de1a9521c",class:{group:true,"is-stretch":this.stretch},part:"group",role:"tablist","aria-label":this.label},this.parsed.map(((t,e)=>{const s=t.value===this.value;return r("button",{key:t.value,class:{segment:true,"is-selected":s},part:s?"segment segment-selected":"segment",type:"button",role:"tab","aria-selected":String(s),disabled:t.disabled,tabindex:s?0:-1,onClick:()=>this.select(t),onKeyDown:t=>this.handleKeyDown(t,e)},t.label,typeof t.count==="number"&&r("span",{class:"count"},t.count))})))}static get watchers(){return{options:[{onOptionsChange:0}]}}static get style(){return i()}},[1,"rk-segmented-control",{options:[1],value:[1025],label:[1],stretch:[4]},undefined,{options:[{onOptionsChange:0}]}]);function a(){if(typeof customElements==="undefined"){return}const t=["rk-segmented-control"];t.forEach((t=>{switch(t){case"rk-segmented-control":if(!customElements.get(n(t))){customElements.define(n(t),o)}break}}))}a();const c=o;const l=a;export{c as RkSegmentedControl,l as defineCustomElement};
2
+ //# sourceMappingURL=rk-segmented-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkSegmentedControlCss","RkSegmentedControl","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","options","label","stretch","parsed","handleKeyDown","event","index","step","key","preventDefault","items","filter","option","disabled","length","currentIndex","indexOf","next","select","onOptionsChange","parseOptions","componentWillLoad","Array","isArray","trim","decoded","JSON","parse","console","warn","value","rkSegmentChange","emit","render","h","class","group","part","role","map","selected","segment","type","String","tabindex","onClick","onKeyDown","count"],"sources":["src/components/rk-segmented-control/rk-segmented-control.css?tag=rk-segmented-control&encapsulation=shadow","src/components/rk-segmented-control/rk-segmented-control.tsx"],"sourcesContent":[":host {\n display: inline-block;\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n max-width: 100%;\n}\n\n.group {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--rk-surface-2, #fdf5ef);\n border: 1px solid var(--rk-border, #ecdfd4);\n border-radius: var(--rk-radius-pill, 999px);\n max-width: 100%;\n overflow-x: auto;\n scrollbar-width: none;\n}\n\n.group::-webkit-scrollbar {\n display: none;\n}\n\n.group.is-stretch {\n display: flex;\n width: 100%;\n}\n\n.segment {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: 0 0 auto;\n padding: 8px 16px;\n border: 0;\n border-radius: var(--rk-radius-pill, 999px);\n background: transparent;\n color: var(--rk-ink-2, #52443c);\n font: inherit;\n font-size: 0.88em;\n font-weight: 550;\n line-height: 1;\n white-space: nowrap;\n cursor: pointer;\n transition: background var(--rk-transition), color var(--rk-transition), box-shadow var(--rk-transition);\n}\n\n.group.is-stretch .segment {\n flex: 1 1 0;\n justify-content: center;\n}\n\n.segment:hover:not(:disabled):not(.is-selected) {\n background: rgba(0, 0, 0, 0.04);\n color: var(--rk-ink, #211a16);\n}\n\n.segment:focus-visible {\n outline: none;\n box-shadow: var(--rk-focus-ring);\n}\n\n.segment.is-selected {\n background: var(--rk-surface, #fff);\n color: var(--rk-ink, #211a16);\n box-shadow: var(--rk-shadow-sm);\n font-weight: 650;\n}\n\n.segment:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n.count {\n font-size: 0.85em;\n font-weight: 650;\n color: var(--rk-muted, #857166);\n font-variant-numeric: tabular-nums;\n}\n\n.segment.is-selected .count {\n color: var(--rk-primary, #d94f1b);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .segment {\n transition: none;\n }\n}\n","import { Component, Event, EventEmitter, h, Prop, Watch } from '@stencil/core';\n\nexport interface RkSegmentOption {\n label: string;\n value: string;\n /** Optional trailing count, e.g. number of items in that segment. */\n count?: number;\n disabled?: boolean;\n}\n\n/**\n * A single-select segmented control, used for sorting and view switching.\n *\n * `options` is a complex property. Frameworks should assign it as a DOM\n * property; for plain HTML it also accepts a JSON string attribute.\n */\n@Component({\n tag: 'rk-segmented-control',\n styleUrl: 'rk-segmented-control.css',\n shadow: true,\n})\nexport class RkSegmentedControl {\n /** The available segments. Accepts an array or a JSON-encoded string. */\n @Prop() options: RkSegmentOption[] | string = [];\n\n /** The value of the selected segment. */\n @Prop({ mutable: true }) value?: string;\n\n /** Accessible label for the group. */\n @Prop() label = 'View options';\n\n /** Stretches the control to fill its container. */\n @Prop() stretch = false;\n\n /** Emitted with the newly selected value. */\n @Event({ eventName: 'rkSegmentChange' }) rkSegmentChange!: EventEmitter<string>;\n\n private parsed: RkSegmentOption[] = [];\n\n @Watch('options')\n protected onOptionsChange() {\n this.parseOptions();\n }\n\n componentWillLoad() {\n this.parseOptions();\n }\n\n /**\n * Attributes can only carry strings, so a JSON payload is accepted as a\n * fallback for consumers that cannot set DOM properties.\n */\n private parseOptions() {\n if (Array.isArray(this.options)) {\n this.parsed = this.options;\n return;\n }\n if (typeof this.options === 'string' && this.options.trim()) {\n try {\n const decoded = JSON.parse(this.options);\n this.parsed = Array.isArray(decoded) ? decoded : [];\n } catch {\n console.warn('[rk-segmented-control] `options` is not valid JSON:', this.options);\n this.parsed = [];\n }\n return;\n }\n this.parsed = [];\n }\n\n private select(option: RkSegmentOption) {\n if (option.disabled || option.value === this.value) return;\n this.value = option.value;\n this.rkSegmentChange.emit(option.value);\n }\n\n private handleKeyDown = (event: KeyboardEvent, index: number) => {\n const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;\n if (step === 0) return;\n event.preventDefault();\n\n const items = this.parsed.filter(option => !option.disabled);\n if (items.length === 0) return;\n const currentIndex = items.indexOf(this.parsed[index]);\n const next = items[(currentIndex + step + items.length) % items.length];\n this.select(next);\n };\n\n render() {\n return (\n <div class={{ group: true, 'is-stretch': this.stretch }} part=\"group\" role=\"tablist\" aria-label={this.label}>\n {this.parsed.map((option, index) => {\n const selected = option.value === this.value;\n return (\n <button\n key={option.value}\n class={{ segment: true, 'is-selected': selected }}\n part={selected ? 'segment segment-selected' : 'segment'}\n type=\"button\"\n role=\"tab\"\n aria-selected={String(selected)}\n disabled={option.disabled}\n tabindex={selected ? 0 : -1}\n onClick={() => this.select(option)}\n onKeyDown={event => this.handleKeyDown(event, index)}\n >\n {option.label}\n {typeof option.count === 'number' && <span class=\"count\">{option.count}</span>}\n </button>\n );\n })}\n </div>\n );\n }\n}\n"],"mappings":"2DAAA,MAAMA,EAAwB,IAAM,m8C,MCqBvBC,EAAkBC,EAAA,MAAAD,UAAAE,EAL/B,WAAAC,CAAAC,G,iHAOUC,KAAAC,QAAsC,GAMtCD,KAAAE,MAAQ,eAGRF,KAAAG,QAAU,MAKVH,KAAAI,OAA4B,GAuC5BJ,KAAAK,cAAgB,CAACC,EAAsBC,KAC7C,MAAMC,EAAOF,EAAMG,MAAQ,aAAe,EAAIH,EAAMG,MAAQ,aAAc,EAAK,EAC/E,GAAID,IAAS,EAAG,OAChBF,EAAMI,iBAEN,MAAMC,EAAQX,KAAKI,OAAOQ,QAAOC,IAAWA,EAAOC,WACnD,GAAIH,EAAMI,SAAW,EAAG,OACxB,MAAMC,EAAeL,EAAMM,QAAQjB,KAAKI,OAAOG,IAC/C,MAAMW,EAAOP,GAAOK,EAAeR,EAAOG,EAAMI,QAAUJ,EAAMI,QAChEf,KAAKmB,OAAOD,EAAK,CA6BpB,CA1EW,eAAAE,GACRpB,KAAKqB,c,CAGP,iBAAAC,GACEtB,KAAKqB,c,CAOC,YAAAA,GACN,GAAIE,MAAMC,QAAQxB,KAAKC,SAAU,CAC/BD,KAAKI,OAASJ,KAAKC,QACnB,M,CAEF,UAAWD,KAAKC,UAAY,UAAYD,KAAKC,QAAQwB,OAAQ,CAC3D,IACE,MAAMC,EAAUC,KAAKC,MAAM5B,KAAKC,SAChCD,KAAKI,OAASmB,MAAMC,QAAQE,GAAWA,EAAU,E,CACjD,MACAG,QAAQC,KAAK,sDAAuD9B,KAAKC,SACzED,KAAKI,OAAS,E,CAEhB,M,CAEFJ,KAAKI,OAAS,E,CAGR,MAAAe,CAAON,GACb,GAAIA,EAAOC,UAAYD,EAAOkB,QAAU/B,KAAK+B,MAAO,OACpD/B,KAAK+B,MAAQlB,EAAOkB,MACpB/B,KAAKgC,gBAAgBC,KAAKpB,EAAOkB,M,CAenC,MAAAG,GACE,OACEC,EAAA,OAAA1B,IAAA,2CAAK2B,MAAO,CAAEC,MAAO,KAAM,aAAcrC,KAAKG,SAAWmC,KAAK,QAAQC,KAAK,UAAS,aAAavC,KAAKE,OACnGF,KAAKI,OAAOoC,KAAI,CAAC3B,EAAQN,KACxB,MAAMkC,EAAW5B,EAAOkB,QAAU/B,KAAK+B,MACvC,OACEI,EAAA,UACE1B,IAAKI,EAAOkB,MACZK,MAAO,CAAEM,QAAS,KAAM,cAAeD,GACvCH,KAAMG,EAAW,2BAA6B,UAC9CE,KAAK,SACLJ,KAAK,MAAK,gBACKK,OAAOH,GACtB3B,SAAUD,EAAOC,SACjB+B,SAAUJ,EAAW,GAAI,EACzBK,QAAS,IAAM9C,KAAKmB,OAAON,GAC3BkC,UAAWzC,GAASN,KAAKK,cAAcC,EAAOC,IAE7CM,EAAOX,aACAW,EAAOmC,QAAU,UAAYb,EAAA,QAAMC,MAAM,SAASvB,EAAOmC,OAC1D,I","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface RkTagInput extends Components.RkTagInput, HTMLElement {}
4
+ export const RkTagInput: {
5
+ prototype: RkTagInput;
6
+ new (): RkTagInput;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,2 @@
1
+ import{p as t,H as e,c as r,h as a,a as s,t as i}from"./index.js";const o=()=>`:host{display:block;font-family:var(--rk-font);font-size:var(--rk-font-size, 15px);color:var(--rk-ink, #211a16)}.label{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:7px;font-size:0.88em;font-weight:600;color:var(--rk-ink-2, #52443c);cursor:text}.counter{font-size:0.88em;font-weight:500;color:var(--rk-muted, #857166);font-variant-numeric:tabular-nums}.shell{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding:8px 10px;min-height:46px;background:var(--rk-surface, #fff);border:1px solid var(--rk-border, #ecdfd4);border-radius:var(--rk-radius, 14px);cursor:text;transition:border-color var(--rk-transition), box-shadow var(--rk-transition)}.shell:focus-within{border-color:var(--rk-primary, #d94f1b);box-shadow:var(--rk-focus-ring)}.shell.has-error{border-color:var(--rk-danger, #c2410c)}.shell.has-error:focus-within{box-shadow:0 0 0 3px rgba(194, 65, 12, 0.24)}.shell.is-disabled{opacity:0.6;cursor:not-allowed;background:var(--rk-surface-2, #fdf5ef)}.tag{display:inline-flex;align-items:center;gap:2px;padding:4px 4px 4px 11px;border-radius:var(--rk-radius-pill, 999px);background:var(--rk-primary-soft, #fdeee6);color:var(--rk-primary-strong, #b23c11);font-size:0.85em;font-weight:600;max-width:100%}.tag-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tag-remove{display:inline-flex;align-items:center;justify-content:center;width:19px;height:19px;padding:0;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer;opacity:0.7;transition:background var(--rk-transition), opacity var(--rk-transition)}.tag-remove:hover:not(:disabled){opacity:1;background:rgba(178, 60, 17, 0.16)}.tag-remove:focus-visible{outline:none;opacity:1;box-shadow:var(--rk-focus-ring)}.tag-remove:disabled{cursor:not-allowed}.tag-remove svg{width:10px;height:10px}.entry{flex:1 1 120px;min-width:110px;border:0;outline:none;background:transparent;font:inherit;color:inherit;padding:5px 2px}.entry::placeholder{color:var(--rk-muted, #857166)}.entry:disabled{cursor:not-allowed}.error{margin:7px 0 0;font-size:0.84em;color:var(--rk-danger, #c2410c);font-weight:550}@media (prefers-reduced-motion: reduce){.shell,.tag-remove{transition:none}}`;const n=t(class t extends e{constructor(t){super();if(t!==false){this.__registerHost()}this.__attachShadow();this.rkTagsChange=r(this,"rkTagsChange");this.values=[];this.placeholder="Add a tag and press Enter";this.maxTags=0;this.disabled=false;this.draft="";this.tags=[];this.handleKeyDown=t=>{if(t.key==="Enter"||t.key===","){t.preventDefault();this.addDraft()}else if(t.key==="Backspace"&&this.draft===""&&this.tags.length>0){t.preventDefault();this.removeAt(this.tags.length-1)}}}onValuesChange(){this.syncTags()}componentWillLoad(){this.syncTags()}syncTags(){const t=this.values;if(Array.isArray(t)){this.tags=t.filter((t=>typeof t==="string"));return}if(typeof t==="string"&&t.trim()){const e=t.trim();if(e.startsWith("[")){try{const t=JSON.parse(e);this.tags=Array.isArray(t)?t.map(String):[];return}catch{}}this.tags=e.split(",").map((t=>t.trim())).filter(Boolean);return}this.tags=[]}get atCapacity(){return this.maxTags>0&&this.tags.length>=this.maxTags}commit(t){this.tags=t;this.rkTagsChange.emit([...t])}addDraft(){const t=this.draft.split(",").map((t=>t.trim())).filter(Boolean);if(t.length===0)return;const e=[...this.tags];for(const r of t){if(this.maxTags>0&&e.length>=this.maxTags)break;if(e.some((t=>t.toLowerCase()===r.toLowerCase())))continue;e.push(r)}this.draft="";if(e.length!==this.tags.length)this.commit(e)}removeAt(t){this.commit(this.tags.filter(((e,r)=>r!==t)))}render(){return a(s,{key:"446657dc603ffa9e4d14ee5c54c947aef90bab4f"},this.label&&a("label",{key:"37575fae490ba8e1a03a3aa6e25ba46d2b364d9e",class:"label",part:"label",onClick:()=>this.inputEl?.focus()},this.label,this.maxTags>0&&a("span",{key:"e29c5d1fd9038cee4707c310adfb88ce7cc75308",class:"counter"},this.tags.length,"/",this.maxTags)),a("div",{key:"13d171bce0dd090bd3034e0150e2def80f493960",class:{shell:true,"is-disabled":this.disabled,"has-error":!!this.error},part:"shell",onClick:()=>!this.disabled&&this.inputEl?.focus()},this.tags.map(((t,e)=>a("span",{class:"tag",part:"tag",key:`${t}-${e}`},a("span",{class:"tag-text"},t),a("button",{class:"tag-remove",type:"button","aria-label":`Remove ${t}`,disabled:this.disabled,onClick:t=>{t.stopPropagation();this.removeAt(e)}},a("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.6","stroke-linecap":"round","aria-hidden":"true"},a("path",{d:"M6 6l12 12M18 6 6 18"})))))),a("input",{key:"8ccdc5e12bd89f7c6b7b8d3c0f5bf80ec7473224",ref:t=>this.inputEl=t,class:"entry",part:"input",type:"text",value:this.draft,placeholder:this.tags.length===0?this.placeholder:this.atCapacity?"":"Add another…","aria-label":this.label??"Add a tag",disabled:this.disabled||this.atCapacity,autocomplete:"off",onInput:t=>this.draft=t.target.value,onKeyDown:this.handleKeyDown,onBlur:()=>this.addDraft()})),this.error&&a("p",{key:"31e84622ac580903e7ebb6af7f57b1842572ce9f",class:"error",part:"error",role:"alert"},this.error))}static get watchers(){return{values:[{onValuesChange:0}]}}static get style(){return o()}},[1,"rk-tag-input",{values:[1],placeholder:[1],label:[1],maxTags:[2,"max-tags"],disabled:[4],error:[1],draft:[32],tags:[32]},undefined,{values:[{onValuesChange:0}]}]);function l(){if(typeof customElements==="undefined"){return}const t=["rk-tag-input"];t.forEach((t=>{switch(t){case"rk-tag-input":if(!customElements.get(i(t))){customElements.define(i(t),n)}break}}))}l();const c=n;const d=l;export{c as RkTagInput,d as defineCustomElement};
2
+ //# sourceMappingURL=rk-tag-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["rkTagInputCss","RkTagInput","__stencil_proxyCustomElement","HTMLElement","constructor","registerHost","this","values","placeholder","maxTags","disabled","draft","tags","handleKeyDown","event","key","preventDefault","addDraft","length","removeAt","onValuesChange","syncTags","componentWillLoad","incoming","Array","isArray","filter","tag","trim","trimmed","startsWith","decoded","JSON","parse","map","String","split","Boolean","atCapacity","commit","next","rkTagsChange","emit","candidates","candidate","some","toLowerCase","push","index","_","position","render","h","Host","label","class","part","onClick","inputEl","focus","shell","error","type","stopPropagation","viewBox","fill","stroke","d","ref","el","value","autocomplete","onInput","target","onKeyDown","onBlur","role"],"sources":["src/components/rk-tag-input/rk-tag-input.css?tag=rk-tag-input&encapsulation=shadow","src/components/rk-tag-input/rk-tag-input.tsx"],"sourcesContent":[":host {\n display: block;\n font-family: var(--rk-font);\n font-size: var(--rk-font-size, 15px);\n color: var(--rk-ink, #211a16);\n}\n\n.label {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n margin-bottom: 7px;\n font-size: 0.88em;\n font-weight: 600;\n color: var(--rk-ink-2, #52443c);\n cursor: text;\n}\n\n.counter {\n font-size: 0.88em;\n font-weight: 500;\n color: var(--rk-muted, #857166);\n font-variant-numeric: tabular-nums;\n}\n\n.shell {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n padding: 8px 10px;\n min-height: 46px;\n background: var(--rk-surface, #fff);\n border: 1px solid var(--rk-border, #ecdfd4);\n border-radius: var(--rk-radius, 14px);\n cursor: text;\n transition: border-color var(--rk-transition), box-shadow var(--rk-transition);\n}\n\n.shell:focus-within {\n border-color: var(--rk-primary, #d94f1b);\n box-shadow: var(--rk-focus-ring);\n}\n\n.shell.has-error {\n border-color: var(--rk-danger, #c2410c);\n}\n\n.shell.has-error:focus-within {\n box-shadow: 0 0 0 3px rgba(194, 65, 12, 0.24);\n}\n\n.shell.is-disabled {\n opacity: 0.6;\n cursor: not-allowed;\n background: var(--rk-surface-2, #fdf5ef);\n}\n\n.tag {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 4px 4px 4px 11px;\n border-radius: var(--rk-radius-pill, 999px);\n background: var(--rk-primary-soft, #fdeee6);\n color: var(--rk-primary-strong, #b23c11);\n font-size: 0.85em;\n font-weight: 600;\n max-width: 100%;\n}\n\n.tag-text {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.tag-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 19px;\n height: 19px;\n padding: 0;\n border: 0;\n border-radius: 50%;\n background: transparent;\n color: inherit;\n cursor: pointer;\n opacity: 0.7;\n transition: background var(--rk-transition), opacity var(--rk-transition);\n}\n\n.tag-remove:hover:not(:disabled) {\n opacity: 1;\n background: rgba(178, 60, 17, 0.16);\n}\n\n.tag-remove:focus-visible {\n outline: none;\n opacity: 1;\n box-shadow: var(--rk-focus-ring);\n}\n\n.tag-remove:disabled {\n cursor: not-allowed;\n}\n\n.tag-remove svg {\n width: 10px;\n height: 10px;\n}\n\n.entry {\n flex: 1 1 120px;\n min-width: 110px;\n border: 0;\n outline: none;\n background: transparent;\n font: inherit;\n color: inherit;\n padding: 5px 2px;\n}\n\n.entry::placeholder {\n color: var(--rk-muted, #857166);\n}\n\n.entry:disabled {\n cursor: not-allowed;\n}\n\n.error {\n margin: 7px 0 0;\n font-size: 0.84em;\n color: var(--rk-danger, #c2410c);\n font-weight: 550;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .shell,\n .tag-remove {\n transition: none;\n }\n}\n","import { Component, Event, EventEmitter, h, Host, Prop, State, Watch } from '@stencil/core';\n\n/**\n * A tag / token editor used for recipe tags and free-form ingredient lists.\n *\n * `values` is an array property — the SvelteKit app assigns it as a DOM\n * property. A JSON-encoded or comma-separated string attribute also works.\n */\n@Component({\n tag: 'rk-tag-input',\n styleUrl: 'rk-tag-input.css',\n shadow: true,\n})\nexport class RkTagInput {\n /** Current tags. Array, JSON string, or comma-separated string. */\n @Prop() values: string[] | string = [];\n\n /** Placeholder for the entry field. */\n @Prop() placeholder = 'Add a tag and press Enter';\n\n /** Visible field label. */\n @Prop() label?: string;\n\n /** Maximum number of tags. `0` means unlimited. */\n @Prop() maxTags = 0;\n\n /** Prevent editing. */\n @Prop() disabled = false;\n\n /** Validation message rendered under the field. */\n @Prop() error?: string;\n\n /** Emitted with the full, updated list whenever tags change. */\n @Event({ eventName: 'rkTagsChange' }) rkTagsChange!: EventEmitter<string[]>;\n\n @State() private draft = '';\n @State() private tags: string[] = [];\n\n private inputEl?: HTMLInputElement;\n\n @Watch('values')\n protected onValuesChange() {\n this.syncTags();\n }\n\n componentWillLoad() {\n this.syncTags();\n }\n\n private syncTags() {\n const incoming = this.values;\n if (Array.isArray(incoming)) {\n this.tags = incoming.filter(tag => typeof tag === 'string');\n return;\n }\n if (typeof incoming === 'string' && incoming.trim()) {\n const trimmed = incoming.trim();\n if (trimmed.startsWith('[')) {\n try {\n const decoded = JSON.parse(trimmed);\n this.tags = Array.isArray(decoded) ? decoded.map(String) : [];\n return;\n } catch {\n /* fall through to comma parsing */\n }\n }\n this.tags = trimmed\n .split(',')\n .map(tag => tag.trim())\n .filter(Boolean);\n return;\n }\n this.tags = [];\n }\n\n private get atCapacity() {\n return this.maxTags > 0 && this.tags.length >= this.maxTags;\n }\n\n private commit(next: string[]) {\n this.tags = next;\n this.rkTagsChange.emit([...next]);\n }\n\n private addDraft() {\n const candidates = this.draft\n .split(',')\n .map(tag => tag.trim())\n .filter(Boolean);\n if (candidates.length === 0) return;\n\n const next = [...this.tags];\n for (const candidate of candidates) {\n if (this.maxTags > 0 && next.length >= this.maxTags) break;\n // Case-insensitive de-duplication keeps \"Vegan\" and \"vegan\" from coexisting.\n if (next.some(tag => tag.toLowerCase() === candidate.toLowerCase())) continue;\n next.push(candidate);\n }\n\n this.draft = '';\n if (next.length !== this.tags.length) this.commit(next);\n }\n\n private removeAt(index: number) {\n this.commit(this.tags.filter((_, position) => position !== index));\n }\n\n private handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ',') {\n event.preventDefault();\n this.addDraft();\n } else if (event.key === 'Backspace' && this.draft === '' && this.tags.length > 0) {\n event.preventDefault();\n this.removeAt(this.tags.length - 1);\n }\n };\n\n render() {\n return (\n <Host>\n {this.label && (\n <label class=\"label\" part=\"label\" onClick={() => this.inputEl?.focus()}>\n {this.label}\n {this.maxTags > 0 && (\n <span class=\"counter\">\n {this.tags.length}/{this.maxTags}\n </span>\n )}\n </label>\n )}\n\n <div\n class={{ shell: true, 'is-disabled': this.disabled, 'has-error': !!this.error }}\n part=\"shell\"\n onClick={() => !this.disabled && this.inputEl?.focus()}\n >\n {this.tags.map((tag, index) => (\n <span class=\"tag\" part=\"tag\" key={`${tag}-${index}`}>\n <span class=\"tag-text\">{tag}</span>\n <button\n class=\"tag-remove\"\n type=\"button\"\n aria-label={`Remove ${tag}`}\n disabled={this.disabled}\n onClick={event => {\n event.stopPropagation();\n this.removeAt(index);\n }}\n >\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\" aria-hidden=\"true\">\n <path d=\"M6 6l12 12M18 6 6 18\" />\n </svg>\n </button>\n </span>\n ))}\n\n <input\n ref={el => (this.inputEl = el)}\n class=\"entry\"\n part=\"input\"\n type=\"text\"\n value={this.draft}\n placeholder={this.tags.length === 0 ? this.placeholder : this.atCapacity ? '' : 'Add another…'}\n aria-label={this.label ?? 'Add a tag'}\n disabled={this.disabled || this.atCapacity}\n autocomplete=\"off\"\n onInput={event => (this.draft = (event.target as HTMLInputElement).value)}\n onKeyDown={this.handleKeyDown}\n onBlur={() => this.addDraft()}\n />\n </div>\n\n {this.error && (\n <p class=\"error\" part=\"error\" role=\"alert\">\n {this.error}\n </p>\n )}\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}