@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.
- package/README.md +108 -277
- package/dist/cjs/index-BEr8BsSA.js +1712 -0
- package/dist/cjs/index-BEr8BsSA.js.map +1 -0
- package/dist/cjs/index.cjs.js +5 -0
- package/dist/cjs/index.cjs.js.map +1 -0
- package/dist/cjs/loader.cjs.js +15 -0
- package/dist/cjs/loader.cjs.js.map +1 -0
- package/dist/cjs/recipe-kit.cjs.js +27 -0
- package/dist/cjs/recipe-kit.cjs.js.map +1 -0
- package/dist/cjs/rk-badge_10.cjs.entry.js +638 -0
- package/dist/cjs/rk-badge_10.cjs.entry.js.map +1 -0
- package/dist/collection/collection-manifest.json +22 -0
- package/dist/collection/components/rk-badge/rk-badge.js +97 -0
- package/dist/collection/components/rk-badge/rk-badge.js.map +1 -0
- package/dist/collection/components/rk-chip/rk-chip.js +245 -0
- package/dist/collection/components/rk-chip/rk-chip.js.map +1 -0
- package/dist/collection/components/rk-empty-state/rk-empty-state.js +138 -0
- package/dist/collection/components/rk-empty-state/rk-empty-state.js.map +1 -0
- package/dist/collection/components/rk-meal-slot/rk-meal-slot.js +312 -0
- package/dist/collection/components/rk-meal-slot/rk-meal-slot.js.map +1 -0
- package/dist/collection/components/rk-modal/rk-modal.js +256 -0
- package/dist/collection/components/rk-modal/rk-modal.js.map +1 -0
- package/dist/collection/components/rk-rating/rk-rating.js +228 -0
- package/dist/collection/components/rk-rating/rk-rating.js.map +1 -0
- package/dist/collection/components/rk-recipe-card/rk-recipe-card.js +366 -0
- package/dist/collection/components/rk-recipe-card/rk-recipe-card.js.map +1 -0
- package/dist/collection/components/rk-search-bar/rk-search-bar.js +291 -0
- package/dist/collection/components/rk-search-bar/rk-search-bar.js.map +1 -0
- package/dist/collection/components/rk-segmented-control/rk-segmented-control.js +196 -0
- package/dist/collection/components/rk-segmented-control/rk-segmented-control.js.map +1 -0
- package/dist/collection/components/rk-tag-input/rk-tag-input.js +264 -0
- package/dist/collection/components/rk-tag-input/rk-tag-input.js.map +1 -0
- package/dist/collection/index.js +2 -0
- package/dist/collection/index.js.map +1 -0
- package/dist/components/index.d.ts +35 -0
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/rk-badge.d.ts +11 -0
- package/dist/components/rk-badge.js +2 -0
- package/dist/components/rk-badge.js.map +1 -0
- package/dist/components/rk-chip.d.ts +11 -0
- package/dist/components/rk-chip.js +2 -0
- package/dist/components/rk-chip.js.map +1 -0
- package/dist/components/rk-empty-state.d.ts +11 -0
- package/dist/components/rk-empty-state.js +2 -0
- package/dist/components/rk-empty-state.js.map +1 -0
- package/dist/components/rk-meal-slot.d.ts +11 -0
- package/dist/components/rk-meal-slot.js +2 -0
- package/dist/components/rk-meal-slot.js.map +1 -0
- package/dist/components/rk-modal.d.ts +11 -0
- package/dist/components/rk-modal.js +2 -0
- package/dist/components/rk-modal.js.map +1 -0
- package/dist/components/rk-rating.d.ts +11 -0
- package/dist/components/rk-rating.js +2 -0
- package/dist/components/rk-rating.js.map +1 -0
- package/dist/components/rk-recipe-card.d.ts +11 -0
- package/dist/components/rk-recipe-card.js +2 -0
- package/dist/components/rk-recipe-card.js.map +1 -0
- package/dist/components/rk-search-bar.d.ts +11 -0
- package/dist/components/rk-search-bar.js +2 -0
- package/dist/components/rk-search-bar.js.map +1 -0
- package/dist/components/rk-segmented-control.d.ts +11 -0
- package/dist/components/rk-segmented-control.js +2 -0
- package/dist/components/rk-segmented-control.js.map +1 -0
- package/dist/components/rk-tag-input.d.ts +11 -0
- package/dist/components/rk-tag-input.js +2 -0
- package/dist/components/rk-tag-input.js.map +1 -0
- package/dist/esm/index-Bxo0C8lB.js +1684 -0
- package/dist/esm/index-Bxo0C8lB.js.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/loader.js +13 -0
- package/dist/esm/loader.js.map +1 -0
- package/dist/esm/recipe-kit.js +23 -0
- package/dist/esm/recipe-kit.js.map +1 -0
- package/dist/esm/rk-badge_10.entry.js +627 -0
- package/dist/esm/rk-badge_10.entry.js.map +1 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/recipe-kit/index.esm.js +2 -0
- package/dist/recipe-kit/index.esm.js.map +1 -0
- package/dist/recipe-kit/p-Bxo0C8lB.js +3 -0
- package/dist/recipe-kit/p-Bxo0C8lB.js.map +1 -0
- package/dist/recipe-kit/p-fcb955c7.entry.js +2 -0
- package/dist/recipe-kit/p-fcb955c7.entry.js.map +1 -0
- package/dist/recipe-kit/recipe-kit.css +1 -0
- package/dist/recipe-kit/recipe-kit.esm.js +2 -0
- package/dist/recipe-kit/recipe-kit.esm.js.map +1 -0
- package/dist/recipe-kit/rk-global.css +104 -0
- package/dist/types/components/rk-badge/rk-badge.d.ts +15 -0
- package/dist/types/components/rk-chip/rk-chip.d.ts +37 -0
- package/dist/types/components/rk-empty-state/rk-empty-state.d.ts +19 -0
- package/dist/types/components/rk-meal-slot/rk-meal-slot.d.ts +53 -0
- package/dist/types/components/rk-modal/rk-modal.d.ts +41 -0
- package/dist/types/components/rk-rating/rk-rating.d.ts +26 -0
- package/dist/types/components/rk-recipe-card/rk-recipe-card.d.ts +67 -0
- package/dist/types/components/rk-search-bar/rk-search-bar.d.ts +39 -0
- package/dist/types/components/rk-segmented-control/rk-segmented-control.d.ts +37 -0
- package/dist/types/components/rk-tag-input/rk-tag-input.d.ts +35 -0
- package/{packages/recipe-kit-stencil/src → dist/types}/components.d.ts +1 -1
- package/{packages/recipe-kit-stencil/src/index.ts → dist/types/index.d.ts} +0 -2
- package/dist/types/stencil-public-runtime.d.ts +1873 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +84 -22
- package/.claude/settings.local.json +0 -10
- package/.npmr +0 -1
- package/apps/recipe-web/package.json +0 -31
- package/apps/recipe-web/src/app.css +0 -418
- package/apps/recipe-web/src/app.d.ts +0 -32
- package/apps/recipe-web/src/app.html +0 -25
- package/apps/recipe-web/src/lib/api/mealdb.ts +0 -240
- package/apps/recipe-web/src/lib/components/AppHeader.svelte +0 -290
- package/apps/recipe-web/src/lib/components/ConfirmDialog.svelte +0 -46
- package/apps/recipe-web/src/lib/components/Modal.svelte +0 -33
- package/apps/recipe-web/src/lib/components/RecipeCard.svelte +0 -100
- package/apps/recipe-web/src/lib/components/RecipeForm.svelte +0 -560
- package/apps/recipe-web/src/lib/components/RecipeGrid.svelte +0 -77
- package/apps/recipe-web/src/lib/components/RecipePickerDialog.svelte +0 -185
- package/apps/recipe-web/src/lib/components/Toaster.svelte +0 -111
- package/apps/recipe-web/src/lib/domain/recipe.ts +0 -130
- package/apps/recipe-web/src/lib/domain/validation.ts +0 -189
- package/apps/recipe-web/src/lib/stencil/WebComponent.svelte +0 -145
- package/apps/recipe-web/src/lib/stencil/register.ts +0 -28
- package/apps/recipe-web/src/lib/stores/favorites.svelte.ts +0 -81
- package/apps/recipe-web/src/lib/stores/myRecipes.svelte.ts +0 -98
- package/apps/recipe-web/src/lib/stores/persisted.svelte.ts +0 -73
- package/apps/recipe-web/src/lib/stores/planner.svelte.ts +0 -275
- package/apps/recipe-web/src/lib/stores/theme.svelte.ts +0 -67
- package/apps/recipe-web/src/lib/stores/toast.svelte.ts +0 -66
- package/apps/recipe-web/src/routes/+error.svelte +0 -36
- package/apps/recipe-web/src/routes/+layout.svelte +0 -62
- package/apps/recipe-web/src/routes/+page.svelte +0 -352
- package/apps/recipe-web/src/routes/+page.ts +0 -107
- package/apps/recipe-web/src/routes/favorites/+page.svelte +0 -170
- package/apps/recipe-web/src/routes/my-recipes/+layout.ts +0 -55
- package/apps/recipe-web/src/routes/my-recipes/+page.svelte +0 -180
- package/apps/recipe-web/src/routes/my-recipes/[id]/edit/+page.svelte +0 -104
- package/apps/recipe-web/src/routes/my-recipes/new/+page.svelte +0 -67
- package/apps/recipe-web/src/routes/planner/+page.svelte +0 -422
- package/apps/recipe-web/src/routes/recipes/[id]/+page.svelte +0 -538
- package/apps/recipe-web/src/routes/recipes/[id]/+page.ts +0 -24
- package/apps/recipe-web/static/favicon.svg +0 -8
- package/apps/recipe-web/static/robots.txt +0 -2
- package/apps/recipe-web/svelte.config.js +0 -35
- package/apps/recipe-web/tsconfig.json +0 -14
- package/apps/recipe-web/vite.config.ts +0 -23
- package/packages/recipe-kit-stencil/README.md +0 -185
- package/packages/recipe-kit-stencil/package-lock.json +0 -4772
- package/packages/recipe-kit-stencil/package.json +0 -91
- package/packages/recipe-kit-stencil/src/components/rk-badge/readme.md +0 -38
- package/packages/recipe-kit-stencil/src/components/rk-badge/rk-badge.tsx +0 -31
- package/packages/recipe-kit-stencil/src/components/rk-chip/readme.md +0 -52
- package/packages/recipe-kit-stencil/src/components/rk-chip/rk-chip.tsx +0 -105
- package/packages/recipe-kit-stencil/src/components/rk-empty-state/readme.md +0 -44
- package/packages/recipe-kit-stencil/src/components/rk-empty-state/rk-empty-state.tsx +0 -50
- package/packages/recipe-kit-stencil/src/components/rk-meal-slot/readme.md +0 -58
- package/packages/recipe-kit-stencil/src/components/rk-meal-slot/rk-meal-slot.tsx +0 -182
- package/packages/recipe-kit-stencil/src/components/rk-modal/readme.md +0 -57
- package/packages/recipe-kit-stencil/src/components/rk-modal/rk-modal.tsx +0 -176
- package/packages/recipe-kit-stencil/src/components/rk-rating/readme.md +0 -42
- package/packages/recipe-kit-stencil/src/components/rk-rating/rk-rating.tsx +0 -114
- package/packages/recipe-kit-stencil/src/components/rk-recipe-card/readme.md +0 -66
- package/packages/recipe-kit-stencil/src/components/rk-recipe-card/rk-recipe-card.tsx +0 -179
- package/packages/recipe-kit-stencil/src/components/rk-recipe-card/test/rk-recipe-card.spec.tsx +0 -70
- package/packages/recipe-kit-stencil/src/components/rk-search-bar/readme.md +0 -67
- package/packages/recipe-kit-stencil/src/components/rk-search-bar/rk-search-bar.tsx +0 -152
- package/packages/recipe-kit-stencil/src/components/rk-search-bar/test/rk-search-bar.spec.tsx +0 -93
- package/packages/recipe-kit-stencil/src/components/rk-segmented-control/readme.md +0 -41
- package/packages/recipe-kit-stencil/src/components/rk-segmented-control/rk-segmented-control.tsx +0 -115
- package/packages/recipe-kit-stencil/src/components/rk-tag-input/readme.md +0 -47
- package/packages/recipe-kit-stencil/src/components/rk-tag-input/rk-tag-input.tsx +0 -181
- package/packages/recipe-kit-stencil/src/components/rk-tag-input/test/rk-tag-input.spec.tsx +0 -76
- package/packages/recipe-kit-stencil/src/index.html +0 -259
- package/packages/recipe-kit-stencil/stencil.config.ts +0 -41
- package/packages/recipe-kit-stencil/tsconfig.json +0 -24
- /package/{packages/recipe-kit-stencil/LICENSE → LICENSE} +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-badge/rk-badge.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-chip/rk-chip.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-empty-state/rk-empty-state.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-meal-slot/rk-meal-slot.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-modal/rk-modal.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-rating/rk-rating.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-recipe-card/rk-recipe-card.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-search-bar/rk-search-bar.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-segmented-control/rk-segmented-control.css +0 -0
- /package/{packages/recipe-kit-stencil/src → dist/collection}/components/rk-tag-input/rk-tag-input.css +0 -0
- /package/{packages/recipe-kit-stencil/src/global → dist/collection}/rk-global.css +0 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { h, Host } from "@stencil/core";
|
|
2
|
+
/**
|
|
3
|
+
* A debounced search input with a clear affordance and a slot for extra controls.
|
|
4
|
+
*
|
|
5
|
+
* @slot actions - Rendered to the right of the input, inside the field shell.
|
|
6
|
+
* Useful for a "filters" toggle or a sort control.
|
|
7
|
+
*/
|
|
8
|
+
export class RkSearchBar {
|
|
9
|
+
constructor() {
|
|
10
|
+
/** Current text in the field. Two-way: updated as the user types. */
|
|
11
|
+
this.value = '';
|
|
12
|
+
/** Placeholder shown when the field is empty. */
|
|
13
|
+
this.placeholder = 'Search recipes, ingredients, cuisines…';
|
|
14
|
+
/** Accessible label for the input. */
|
|
15
|
+
this.label = 'Search recipes';
|
|
16
|
+
/** Milliseconds to wait after the last keystroke before emitting `rkSearch`. */
|
|
17
|
+
this.debounce = 350;
|
|
18
|
+
/** Disables the whole control. */
|
|
19
|
+
this.disabled = false;
|
|
20
|
+
/** Shows a busy indicator (e.g. while the app is fetching results). */
|
|
21
|
+
this.loading = false;
|
|
22
|
+
this.focused = false;
|
|
23
|
+
this.handleInput = (event) => {
|
|
24
|
+
const next = event.target.value;
|
|
25
|
+
this.value = next;
|
|
26
|
+
clearTimeout(this.timer);
|
|
27
|
+
this.timer = setTimeout(() => this.emit(next), Math.max(0, this.debounce));
|
|
28
|
+
};
|
|
29
|
+
this.handleKeyDown = (event) => {
|
|
30
|
+
if (event.key === 'Enter') {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
this.emit(this.value);
|
|
33
|
+
}
|
|
34
|
+
else if (event.key === 'Escape' && this.value) {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
this.handleClear();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
this.handleClear = () => {
|
|
40
|
+
clearTimeout(this.timer);
|
|
41
|
+
this.value = '';
|
|
42
|
+
if (this.inputEl)
|
|
43
|
+
this.inputEl.value = '';
|
|
44
|
+
this.rkClear.emit();
|
|
45
|
+
this.rkSearch.emit('');
|
|
46
|
+
this.inputEl?.focus();
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
onValueChange(next, prev) {
|
|
50
|
+
// Keep the DOM input in sync when the value is driven from the outside.
|
|
51
|
+
if (this.inputEl && this.inputEl.value !== next && next !== prev) {
|
|
52
|
+
this.inputEl.value = next ?? '';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
disconnectedCallback() {
|
|
56
|
+
clearTimeout(this.timer);
|
|
57
|
+
}
|
|
58
|
+
/** Programmatically focus the input. */
|
|
59
|
+
async setFocus() {
|
|
60
|
+
this.inputEl?.focus();
|
|
61
|
+
}
|
|
62
|
+
emit(query) {
|
|
63
|
+
clearTimeout(this.timer);
|
|
64
|
+
this.rkSearch.emit(query.trim());
|
|
65
|
+
}
|
|
66
|
+
render() {
|
|
67
|
+
const hasValue = (this.value ?? '').length > 0;
|
|
68
|
+
return (h(Host, { key: 'cf58faf063a6c13bada8f5713f0dcbb582962577' }, h("div", { key: '13bdb192a7cb4fd699ffae8a9f67fba3e1a68c16', class: { shell: true, 'is-focused': this.focused, 'is-disabled': this.disabled }, part: "shell" }, h("span", { key: 'fe65bb803f4e3c01c1bf1eab66ab70658256820e', class: "icon", "aria-hidden": "true" }, h("svg", { key: 'a20ca316e086189ad00f8e9fed05cfa21c43fa10', viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }, h("circle", { key: '8298c51dc269224356a1e3248838e2ff8c20aab3', cx: "11", cy: "11", r: "7" }), h("path", { key: '92acd9c5a363ad4a9e9f14cbcf6b4ff86aae2bf2', d: "m20 20-3.5-3.5" }))), h("input", { key: '5fef80ea1e552630361556381dd09b62874334ca', ref: el => (this.inputEl = el), 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 && h("span", { key: '17c0e5483cc3bea79642192c6cb8548f32071f02', class: "spinner", part: "spinner", "aria-hidden": "true" }), hasValue && !this.loading && (h("button", { key: '7df966f93f1de6a1d3a380c4856f235a671521ad', class: "clear", part: "clear", type: "button", onClick: this.handleClear, "aria-label": "Clear search", disabled: this.disabled }, h("svg", { key: '29457188a630e71e4c29f93939edbcb28862cade', viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "aria-hidden": "true" }, h("path", { key: '64406c87eaaa582151fdf5d1ee7929a6f311cc4c', d: "M6 6l12 12M18 6 6 18" })))), h("span", { key: '7abf5bd0cdb2d15b7143491c5de5216df872deff', class: "actions", part: "actions" }, h("slot", { key: '09fa60e54e72af6c9e7187f3406a11e80d5a3004', name: "actions" }))), this.hint && (h("p", { key: '1dd826505bcfc2cb5b7712adc18e7e29dc814f2b', class: "hint", part: "hint" }, this.hint))));
|
|
69
|
+
}
|
|
70
|
+
static get is() { return "rk-search-bar"; }
|
|
71
|
+
static get encapsulation() { return "shadow"; }
|
|
72
|
+
static get originalStyleUrls() {
|
|
73
|
+
return {
|
|
74
|
+
"$": ["rk-search-bar.css"]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
static get styleUrls() {
|
|
78
|
+
return {
|
|
79
|
+
"$": ["rk-search-bar.css"]
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
static get properties() {
|
|
83
|
+
return {
|
|
84
|
+
"value": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"mutable": true,
|
|
87
|
+
"complexType": {
|
|
88
|
+
"original": "string",
|
|
89
|
+
"resolved": "string",
|
|
90
|
+
"references": {}
|
|
91
|
+
},
|
|
92
|
+
"required": false,
|
|
93
|
+
"optional": false,
|
|
94
|
+
"docs": {
|
|
95
|
+
"tags": [],
|
|
96
|
+
"text": "Current text in the field. Two-way: updated as the user types."
|
|
97
|
+
},
|
|
98
|
+
"getter": false,
|
|
99
|
+
"setter": false,
|
|
100
|
+
"reflect": false,
|
|
101
|
+
"attribute": "value",
|
|
102
|
+
"defaultValue": "''"
|
|
103
|
+
},
|
|
104
|
+
"placeholder": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"mutable": false,
|
|
107
|
+
"complexType": {
|
|
108
|
+
"original": "string",
|
|
109
|
+
"resolved": "string",
|
|
110
|
+
"references": {}
|
|
111
|
+
},
|
|
112
|
+
"required": false,
|
|
113
|
+
"optional": false,
|
|
114
|
+
"docs": {
|
|
115
|
+
"tags": [],
|
|
116
|
+
"text": "Placeholder shown when the field is empty."
|
|
117
|
+
},
|
|
118
|
+
"getter": false,
|
|
119
|
+
"setter": false,
|
|
120
|
+
"reflect": false,
|
|
121
|
+
"attribute": "placeholder",
|
|
122
|
+
"defaultValue": "'Search recipes, ingredients, cuisines\u2026'"
|
|
123
|
+
},
|
|
124
|
+
"label": {
|
|
125
|
+
"type": "string",
|
|
126
|
+
"mutable": false,
|
|
127
|
+
"complexType": {
|
|
128
|
+
"original": "string",
|
|
129
|
+
"resolved": "string",
|
|
130
|
+
"references": {}
|
|
131
|
+
},
|
|
132
|
+
"required": false,
|
|
133
|
+
"optional": false,
|
|
134
|
+
"docs": {
|
|
135
|
+
"tags": [],
|
|
136
|
+
"text": "Accessible label for the input."
|
|
137
|
+
},
|
|
138
|
+
"getter": false,
|
|
139
|
+
"setter": false,
|
|
140
|
+
"reflect": false,
|
|
141
|
+
"attribute": "label",
|
|
142
|
+
"defaultValue": "'Search recipes'"
|
|
143
|
+
},
|
|
144
|
+
"debounce": {
|
|
145
|
+
"type": "number",
|
|
146
|
+
"mutable": false,
|
|
147
|
+
"complexType": {
|
|
148
|
+
"original": "number",
|
|
149
|
+
"resolved": "number",
|
|
150
|
+
"references": {}
|
|
151
|
+
},
|
|
152
|
+
"required": false,
|
|
153
|
+
"optional": false,
|
|
154
|
+
"docs": {
|
|
155
|
+
"tags": [],
|
|
156
|
+
"text": "Milliseconds to wait after the last keystroke before emitting `rkSearch`."
|
|
157
|
+
},
|
|
158
|
+
"getter": false,
|
|
159
|
+
"setter": false,
|
|
160
|
+
"reflect": false,
|
|
161
|
+
"attribute": "debounce",
|
|
162
|
+
"defaultValue": "350"
|
|
163
|
+
},
|
|
164
|
+
"disabled": {
|
|
165
|
+
"type": "boolean",
|
|
166
|
+
"mutable": false,
|
|
167
|
+
"complexType": {
|
|
168
|
+
"original": "boolean",
|
|
169
|
+
"resolved": "boolean",
|
|
170
|
+
"references": {}
|
|
171
|
+
},
|
|
172
|
+
"required": false,
|
|
173
|
+
"optional": false,
|
|
174
|
+
"docs": {
|
|
175
|
+
"tags": [],
|
|
176
|
+
"text": "Disables the whole control."
|
|
177
|
+
},
|
|
178
|
+
"getter": false,
|
|
179
|
+
"setter": false,
|
|
180
|
+
"reflect": false,
|
|
181
|
+
"attribute": "disabled",
|
|
182
|
+
"defaultValue": "false"
|
|
183
|
+
},
|
|
184
|
+
"loading": {
|
|
185
|
+
"type": "boolean",
|
|
186
|
+
"mutable": false,
|
|
187
|
+
"complexType": {
|
|
188
|
+
"original": "boolean",
|
|
189
|
+
"resolved": "boolean",
|
|
190
|
+
"references": {}
|
|
191
|
+
},
|
|
192
|
+
"required": false,
|
|
193
|
+
"optional": false,
|
|
194
|
+
"docs": {
|
|
195
|
+
"tags": [],
|
|
196
|
+
"text": "Shows a busy indicator (e.g. while the app is fetching results)."
|
|
197
|
+
},
|
|
198
|
+
"getter": false,
|
|
199
|
+
"setter": false,
|
|
200
|
+
"reflect": false,
|
|
201
|
+
"attribute": "loading",
|
|
202
|
+
"defaultValue": "false"
|
|
203
|
+
},
|
|
204
|
+
"hint": {
|
|
205
|
+
"type": "string",
|
|
206
|
+
"mutable": false,
|
|
207
|
+
"complexType": {
|
|
208
|
+
"original": "string",
|
|
209
|
+
"resolved": "string",
|
|
210
|
+
"references": {}
|
|
211
|
+
},
|
|
212
|
+
"required": false,
|
|
213
|
+
"optional": true,
|
|
214
|
+
"docs": {
|
|
215
|
+
"tags": [],
|
|
216
|
+
"text": "Optional helper text rendered under the field."
|
|
217
|
+
},
|
|
218
|
+
"getter": false,
|
|
219
|
+
"setter": false,
|
|
220
|
+
"reflect": false,
|
|
221
|
+
"attribute": "hint"
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
static get states() {
|
|
226
|
+
return {
|
|
227
|
+
"focused": {}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
static get events() {
|
|
231
|
+
return [{
|
|
232
|
+
"method": "rkSearch",
|
|
233
|
+
"name": "rkSearch",
|
|
234
|
+
"bubbles": true,
|
|
235
|
+
"cancelable": true,
|
|
236
|
+
"composed": true,
|
|
237
|
+
"docs": {
|
|
238
|
+
"tags": [],
|
|
239
|
+
"text": "Emitted with the (trimmed) query after the debounce window, or on submit."
|
|
240
|
+
},
|
|
241
|
+
"complexType": {
|
|
242
|
+
"original": "string",
|
|
243
|
+
"resolved": "string",
|
|
244
|
+
"references": {}
|
|
245
|
+
}
|
|
246
|
+
}, {
|
|
247
|
+
"method": "rkClear",
|
|
248
|
+
"name": "rkClear",
|
|
249
|
+
"bubbles": true,
|
|
250
|
+
"cancelable": true,
|
|
251
|
+
"composed": true,
|
|
252
|
+
"docs": {
|
|
253
|
+
"tags": [],
|
|
254
|
+
"text": "Emitted when the user clears the field with the clear button or Escape."
|
|
255
|
+
},
|
|
256
|
+
"complexType": {
|
|
257
|
+
"original": "void",
|
|
258
|
+
"resolved": "void",
|
|
259
|
+
"references": {}
|
|
260
|
+
}
|
|
261
|
+
}];
|
|
262
|
+
}
|
|
263
|
+
static get methods() {
|
|
264
|
+
return {
|
|
265
|
+
"setFocus": {
|
|
266
|
+
"complexType": {
|
|
267
|
+
"signature": "() => Promise<void>",
|
|
268
|
+
"parameters": [],
|
|
269
|
+
"references": {
|
|
270
|
+
"Promise": {
|
|
271
|
+
"location": "global",
|
|
272
|
+
"id": "global::Promise"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
"return": "Promise<void>"
|
|
276
|
+
},
|
|
277
|
+
"docs": {
|
|
278
|
+
"text": "Programmatically focus the input.",
|
|
279
|
+
"tags": []
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
static get watchers() {
|
|
285
|
+
return [{
|
|
286
|
+
"propName": "value",
|
|
287
|
+
"methodName": "onValueChange"
|
|
288
|
+
}];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=rk-search-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rk-search-bar.js","sourceRoot":"","sources":["../../../src/components/rk-search-bar/rk-search-bar.tsx"],"names":[],"mappings":"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","sourcesContent":["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"]}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { h } from "@stencil/core";
|
|
2
|
+
/**
|
|
3
|
+
* A single-select segmented control, used for sorting and view switching.
|
|
4
|
+
*
|
|
5
|
+
* `options` is a complex property. Frameworks should assign it as a DOM
|
|
6
|
+
* property; for plain HTML it also accepts a JSON string attribute.
|
|
7
|
+
*/
|
|
8
|
+
export class RkSegmentedControl {
|
|
9
|
+
constructor() {
|
|
10
|
+
/** The available segments. Accepts an array or a JSON-encoded string. */
|
|
11
|
+
this.options = [];
|
|
12
|
+
/** Accessible label for the group. */
|
|
13
|
+
this.label = 'View options';
|
|
14
|
+
/** Stretches the control to fill its container. */
|
|
15
|
+
this.stretch = false;
|
|
16
|
+
this.parsed = [];
|
|
17
|
+
this.handleKeyDown = (event, index) => {
|
|
18
|
+
const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
|
|
19
|
+
if (step === 0)
|
|
20
|
+
return;
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
const items = this.parsed.filter(option => !option.disabled);
|
|
23
|
+
if (items.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
const currentIndex = items.indexOf(this.parsed[index]);
|
|
26
|
+
const next = items[(currentIndex + step + items.length) % items.length];
|
|
27
|
+
this.select(next);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
onOptionsChange() {
|
|
31
|
+
this.parseOptions();
|
|
32
|
+
}
|
|
33
|
+
componentWillLoad() {
|
|
34
|
+
this.parseOptions();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Attributes can only carry strings, so a JSON payload is accepted as a
|
|
38
|
+
* fallback for consumers that cannot set DOM properties.
|
|
39
|
+
*/
|
|
40
|
+
parseOptions() {
|
|
41
|
+
if (Array.isArray(this.options)) {
|
|
42
|
+
this.parsed = this.options;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (typeof this.options === 'string' && this.options.trim()) {
|
|
46
|
+
try {
|
|
47
|
+
const decoded = JSON.parse(this.options);
|
|
48
|
+
this.parsed = Array.isArray(decoded) ? decoded : [];
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
console.warn('[rk-segmented-control] `options` is not valid JSON:', this.options);
|
|
52
|
+
this.parsed = [];
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.parsed = [];
|
|
57
|
+
}
|
|
58
|
+
select(option) {
|
|
59
|
+
if (option.disabled || option.value === this.value)
|
|
60
|
+
return;
|
|
61
|
+
this.value = option.value;
|
|
62
|
+
this.rkSegmentChange.emit(option.value);
|
|
63
|
+
}
|
|
64
|
+
render() {
|
|
65
|
+
return (h("div", { key: 'e2b6eec632ebe51b9f259c60b174126de1a9521c', class: { group: true, 'is-stretch': this.stretch }, part: "group", role: "tablist", "aria-label": this.label }, this.parsed.map((option, index) => {
|
|
66
|
+
const selected = option.value === this.value;
|
|
67
|
+
return (h("button", { key: option.value, class: { segment: true, 'is-selected': selected }, part: selected ? 'segment segment-selected' : 'segment', type: "button", role: "tab", "aria-selected": String(selected), disabled: option.disabled, tabindex: selected ? 0 : -1, onClick: () => this.select(option), onKeyDown: event => this.handleKeyDown(event, index) }, option.label, typeof option.count === 'number' && h("span", { class: "count" }, option.count)));
|
|
68
|
+
})));
|
|
69
|
+
}
|
|
70
|
+
static get is() { return "rk-segmented-control"; }
|
|
71
|
+
static get encapsulation() { return "shadow"; }
|
|
72
|
+
static get originalStyleUrls() {
|
|
73
|
+
return {
|
|
74
|
+
"$": ["rk-segmented-control.css"]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
static get styleUrls() {
|
|
78
|
+
return {
|
|
79
|
+
"$": ["rk-segmented-control.css"]
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
static get properties() {
|
|
83
|
+
return {
|
|
84
|
+
"options": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"mutable": false,
|
|
87
|
+
"complexType": {
|
|
88
|
+
"original": "RkSegmentOption[] | string",
|
|
89
|
+
"resolved": "RkSegmentOption[] | string",
|
|
90
|
+
"references": {
|
|
91
|
+
"RkSegmentOption": {
|
|
92
|
+
"location": "local",
|
|
93
|
+
"path": "/Users/sejal.sharma/NAGP/recipe-ui/packages/recipe-ui-kit/src/components/rk-segmented-control/rk-segmented-control.tsx",
|
|
94
|
+
"id": "src/components/rk-segmented-control/rk-segmented-control.tsx::RkSegmentOption"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"required": false,
|
|
99
|
+
"optional": false,
|
|
100
|
+
"docs": {
|
|
101
|
+
"tags": [],
|
|
102
|
+
"text": "The available segments. Accepts an array or a JSON-encoded string."
|
|
103
|
+
},
|
|
104
|
+
"getter": false,
|
|
105
|
+
"setter": false,
|
|
106
|
+
"reflect": false,
|
|
107
|
+
"attribute": "options",
|
|
108
|
+
"defaultValue": "[]"
|
|
109
|
+
},
|
|
110
|
+
"value": {
|
|
111
|
+
"type": "string",
|
|
112
|
+
"mutable": true,
|
|
113
|
+
"complexType": {
|
|
114
|
+
"original": "string",
|
|
115
|
+
"resolved": "string",
|
|
116
|
+
"references": {}
|
|
117
|
+
},
|
|
118
|
+
"required": false,
|
|
119
|
+
"optional": true,
|
|
120
|
+
"docs": {
|
|
121
|
+
"tags": [],
|
|
122
|
+
"text": "The value of the selected segment."
|
|
123
|
+
},
|
|
124
|
+
"getter": false,
|
|
125
|
+
"setter": false,
|
|
126
|
+
"reflect": false,
|
|
127
|
+
"attribute": "value"
|
|
128
|
+
},
|
|
129
|
+
"label": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"mutable": false,
|
|
132
|
+
"complexType": {
|
|
133
|
+
"original": "string",
|
|
134
|
+
"resolved": "string",
|
|
135
|
+
"references": {}
|
|
136
|
+
},
|
|
137
|
+
"required": false,
|
|
138
|
+
"optional": false,
|
|
139
|
+
"docs": {
|
|
140
|
+
"tags": [],
|
|
141
|
+
"text": "Accessible label for the group."
|
|
142
|
+
},
|
|
143
|
+
"getter": false,
|
|
144
|
+
"setter": false,
|
|
145
|
+
"reflect": false,
|
|
146
|
+
"attribute": "label",
|
|
147
|
+
"defaultValue": "'View options'"
|
|
148
|
+
},
|
|
149
|
+
"stretch": {
|
|
150
|
+
"type": "boolean",
|
|
151
|
+
"mutable": false,
|
|
152
|
+
"complexType": {
|
|
153
|
+
"original": "boolean",
|
|
154
|
+
"resolved": "boolean",
|
|
155
|
+
"references": {}
|
|
156
|
+
},
|
|
157
|
+
"required": false,
|
|
158
|
+
"optional": false,
|
|
159
|
+
"docs": {
|
|
160
|
+
"tags": [],
|
|
161
|
+
"text": "Stretches the control to fill its container."
|
|
162
|
+
},
|
|
163
|
+
"getter": false,
|
|
164
|
+
"setter": false,
|
|
165
|
+
"reflect": false,
|
|
166
|
+
"attribute": "stretch",
|
|
167
|
+
"defaultValue": "false"
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
static get events() {
|
|
172
|
+
return [{
|
|
173
|
+
"method": "rkSegmentChange",
|
|
174
|
+
"name": "rkSegmentChange",
|
|
175
|
+
"bubbles": true,
|
|
176
|
+
"cancelable": true,
|
|
177
|
+
"composed": true,
|
|
178
|
+
"docs": {
|
|
179
|
+
"tags": [],
|
|
180
|
+
"text": "Emitted with the newly selected value."
|
|
181
|
+
},
|
|
182
|
+
"complexType": {
|
|
183
|
+
"original": "string",
|
|
184
|
+
"resolved": "string",
|
|
185
|
+
"references": {}
|
|
186
|
+
}
|
|
187
|
+
}];
|
|
188
|
+
}
|
|
189
|
+
static get watchers() {
|
|
190
|
+
return [{
|
|
191
|
+
"propName": "options",
|
|
192
|
+
"methodName": "onOptionsChange"
|
|
193
|
+
}];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=rk-segmented-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rk-segmented-control.js","sourceRoot":"","sources":["../../../src/components/rk-segmented-control/rk-segmented-control.tsx"],"names":[],"mappings":"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","sourcesContent":["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"]}
|