@htmlbricks/hb-searchbar 0.71.35 → 0.71.37

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 CHANGED
@@ -1,47 +1,187 @@
1
- ## `hb-searchbar` searchbar
1
+ # `hb-searchbar` (searchbar)
2
2
 
3
3
  **Category:** utilities
4
- **Tags:** utilities, search
4
+ **Tags:** utilities, search
5
+ **Package:** `@htmlbricks/hb-searchbar`
5
6
 
6
- ### What it does
7
+ ## Overview
7
8
 
8
- Search field with optional dropdown `searchlist` (id, text, icons, badges, tags, URLs). Configure `value`, `searchlabel`, `textarea`, `minlength`, `disable_preview`, `disabled`, and CSS parts for the input and menu. Dispatches `search` and `clear`.
9
+ `hb-searchbar` is a Bulma-styled search control that lives in a shadow root. It renders either a single-line `<input type="search">` or a multiline `<textarea>`, an in-field submit (magnifier) button, and an optional suggestion dropdown driven by a `searchlist` you pass in.
9
10
 
10
- ### Custom element
11
+ Use it when you want a self-contained query field with debounced “search while typing”, optional fixed or fuzzy-matched suggestions, rich rows (icons, badges, tags, links), and explicit `search` / `clear` custom events for your host application.
11
12
 
12
- `hb-searchbar`
13
+ ## Custom element
13
14
 
14
- ### Attributes (snake_case; use string values in HTML)
15
+ ```html
16
+ <hb-searchbar …></hb-searchbar>
17
+ ```
18
+
19
+ ## Attributes and properties
20
+
21
+ Web component attributes are **strings**. For structured data (`searchlist`, `input_info`), pass **JSON** as a string attribute (or set the corresponding property with a parsed object in JavaScript). Boolean-like flags use **`yes`** / **`no`** where noted.
22
+
23
+ | Name | Required | Description |
24
+ |------|----------|-------------|
25
+ | `value` | Yes | Current query text. |
26
+ | `id` | No | Host id string; included on `clear` event detail. |
27
+ | `style` | No | Inline style string for the host (optional). |
28
+ | `searchlabel` | No | Placeholder text. Default: `"Search"`. |
29
+ | `minlength` | No | Minimum query length (number) before input-driven search runs and before the preview can open; default `0`. Compares `value.length` to this number. |
30
+ | `searchlist` | No | Array of suggestions (`TSearchListItem[]`). From HTML, use a JSON string. Parsed at runtime if a string is received. |
31
+ | `input_info` | No | Single `TSearchListItem` shown when its `text` equals the current `value` (JSON string from HTML). |
32
+ | `textarea` | No | Multiline mode: `"yes"`, `"true"`, or `""` (empty string) enables `<textarea>`; otherwise a search `<input>` is used. |
33
+ | `disable_preview` | No | When `"yes"`, `"true"`, or `"on"`, the suggestion dropdown does not open. Any other value (including `"no"`, `"false"`, `"off"`) allows preview when other conditions are met. |
34
+ | `disabled` | No | `"yes"` disables the field and action buttons; `"no"` or omitted leaves them enabled. |
35
+
36
+ ### `TSearchListItem` shape
37
+
38
+ Each suggestion (and `input_info`) uses:
39
+
40
+ | Field | Type | Notes |
41
+ |-------|------|--------|
42
+ | `id` | string | Required stable id for the row. |
43
+ | `text` | string | Primary label. |
44
+ | `url` | string | Optional link target for the row. |
45
+ | `icon` | string | Optional Bootstrap Icons icon name (without `bi-` prefix in markup; the component uses `bi bi-{icon}` classes). |
46
+ | `number_of_results` | number | Optional count display. |
47
+ | `fixed` | boolean | When `true`, the row stays visible regardless of the current filter. |
48
+ | `tags` | `TSearchListItemTag[]` | Optional chips: `text`, `color`, `icon`. |
49
+ | `badge` | `TSearchListItemBadge` | Optional badge: `text`, `color`, `icon`. |
50
+
51
+ Tags and badges use Bulma-style color names (for example `primary`, `success`, `danger`) as consumed by the row renderer.
52
+
53
+ ### How the suggestion list behaves
54
+
55
+ - **Filtering:** Non-fixed items are shown when their `text` contains the current `value` (case-insensitive substring match). Items with `fixed: true` are always included.
56
+ - **Opening:** The dropdown is shown when preview is not disabled, the query length is **greater than** `minlength`, and the field is considered “open” after interaction (typing opens it; choosing an action may close it depending on the trigger).
57
+ - **Debounced input search:** After input changes, a **500 ms** debounce runs; if the value is non-empty and satisfies `minlength`, a `search` event fires with `by: "input"`. Enter in the field triggers submit-style search (`by: "button"`) without waiting for the timer.
58
+ - **Submit button:** Clicks dispatch `search` with `by: "button"`.
59
+ - **Picking a suggestion:** Dispatches `search` with `by: "searchlist"` and updates the field text to the chosen item’s `text`.
60
+ - **Clearing:** For the native search input, clearing via the browser’s search clear control dispatches `clear` with `{ id }`. In textarea mode, an explicit clear button empties the value, dispatches `clear`, and closes the dropdown. Clicks outside the host close the dropdown without clearing the value.
61
+
62
+ ## Events
63
+
64
+ Listen with `addEventListener` on the host element.
65
+
66
+ | Event | Detail (TypeScript `Events`) |
67
+ |-------|-------------------------------|
68
+ | `search` | `{ input: string; by: "button" \| "input" \| "searchlist"; item?: TSearchListItem }` — when the user picks a suggestion, **`item`** is the matched list entry; for **`by: "input"`** or **`"button"`**, **`item`** is omitted. |
69
+ | `clear` | `{ id: string }` — the host **`id`** attribute (empty string if unset). |
70
+
71
+ ## Styling
72
+
73
+ ### Bulma CSS variables
74
+
75
+ The component uses Bulma layout and form patterns inside the shadow tree. Theme it with **`--bulma-*`** variables on a wrapping scope or `:root` / `body` so they apply to `:host`. Relevant groups include:
76
+
77
+ - **Accent and focus:** `--bulma-primary`, `--bulma-danger`
78
+ - **Surfaces and chrome:** `--bulma-background`, `--bulma-scheme-main`, `--bulma-border`, `--bulma-border-weak`
79
+ - **Typography:** `--bulma-text`, `--bulma-text-strong`, `--bulma-input-placeholder-color`
80
+ - **Shape and stacking:** `--bulma-radius`, `--bulma-radius-small`, `--bulma-dropdown-content-z`
81
+
82
+ See [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/) for the full variable system.
83
+
84
+ ### Component-specific variables (`--hb-searchbar-*`)
85
+
86
+ These override frosted layers and panel backgrounds (defaults use `color-mix()` with Bulma tokens):
87
+
88
+ - `--hb-searchbar-host-background` — host background at rest
89
+ - `--hb-searchbar-host-background-focus` — host background while focused
90
+ - `--hb-searchbar-input-strip-background` — input row strip
91
+ - `--hb-searchbar-dropdown-panel-background` — open suggestion panel
92
+ - `--hb-searchbar-input-glass-blur` — backdrop blur behind the focused field
93
+ - `--hb-searchbar-input-glass-saturate` — backdrop saturation factor
94
+
95
+ Authoritative descriptions and defaults are listed in `extra/docs.ts` (`styleSetup.vars`).
96
+
97
+ ### CSS shadow parts
98
+
99
+ | Part | Targets |
100
+ |------|---------|
101
+ | `dropdown-menu` | Open suggestion list panel |
102
+ | `search-input` | Native `<input>` or `<textarea>` |
103
+ | `search-input-glass` | Frosted layer behind the field while focused |
104
+ | `search-submit` | In-field magnifier / submit control |
105
+
106
+ Example:
107
+
108
+ ```css
109
+ hb-searchbar::part(search-submit) {
110
+ color: var(--bulma-primary);
111
+ }
112
+ ```
113
+
114
+ ## Icons and assets
15
115
 
16
- - `id`, `style` (optional): strings.
17
- - `value` (required): string — current query text.
18
- - `searchlabel` (optional): string — placeholder for the input (search is triggered by the in-field magnifier or Enter).
19
- - `minlength` (optional): number as string.
20
- - `searchlist` (optional): JSON string — `TSearchListItem[]` (`id`, `text`, optional `url`, `icon`, `tags`, `badge`, `number_of_results`, `fixed`).
21
- - `input_info` (optional): JSON string — single `TSearchListItem` for input adornment.
22
- - `textarea` (optional): `"yes"` | `"true"` | `""` — multiline input mode.
23
- - `disable_preview` (optional): `"yes"` | `"no"` | `"true"` | `"false"` | `"on"` | `"off"`.
24
- - `disabled` (optional): `"yes"` | `"no"` — when `"yes"`, the input/textarea and action buttons are disabled.
116
+ The component loads **Bootstrap Icons** from jsDelivr in the shadow document head (`bootstrap-icons.css`). Icon names in `searchlist` / `input_info` refer to that font set.
25
117
 
26
- ### Events
118
+ ## Slots
27
119
 
28
- - `search`: `{ input: string; by: "button" | "input" | "searchlist" }`.
29
- - `clear`: `{ id: string }`.
120
+ None (`htmlSlots` is empty).
30
121
 
31
- ### Usage notes
122
+ ## Usage notes
32
123
 
33
- - **Browser autofill:** the search field uses `autocomplete="off"` so native address/password suggestions and similar do not target this control (browser support varies; password managers may still offer fills).
124
+ - **Autocomplete:** The control sets `autocomplete="off"`. Browsers may still offer their own UI; behavior varies.
125
+ - **Storybook:** Controls may expose names like `initial_value` for demos; the runtime contract for authors is `types/webcomponent.type.d.ts` (`value` is the live bound field).
126
+ - **Structured props from HTML:** Always serialize `searchlist` and `input_info` as JSON strings on attributes; never rely on passing raw objects through HTML attributes.
34
127
 
35
- - **CSS parts:** `dropdown-menu`, `search-input`, `search-input-glass` (frosted layer under the field when the input is focused), `search-submit` (magnifier button inside the field).
36
- - **Styling:** Bulma `field` with a single expanded control; the search icon sits on the right as a `search-submit` control. Dropdown and field styles live in the shadow root (`styles/bulma.scss` + `webcomponent.scss`). Prefer [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/) on the host or ancestors: e.g. `--bulma-primary` (focus glow, search-button hover, suggestion row accents), `--bulma-background`, `--bulma-border`, and `--bulma-primary` (host strip: default resting/focus tints on `hb-searchbar` itself; input/textarea are transparent at rest so that shows through), `--bulma-scheme-main`, `--bulma-border-weak`, `--bulma-text`, `--bulma-text-strong`, `--bulma-input-placeholder-color`, `--bulma-danger` (clear button), `--bulma-radius`, `--bulma-radius-small`, `--bulma-dropdown-content-z`. Component-only: `--hb-searchbar-host-background`, `--hb-searchbar-host-background-focus` (:host), `--hb-searchbar-input-strip-background` (darker input row at rest), `--hb-searchbar-dropdown-panel-background` (lighter list panel), `--hb-searchbar-input-glass-blur`, `--hb-searchbar-input-glass-saturate` (frosted layer on input focus only). The primary-colored diffuse glow while the input/textarea is focused wraps the whole root (including the open dropdown) as one outline.
37
- - Storybook may list `initial_value`; runtime props follow `webcomponent.type.d.ts` (`value` is required).
128
+ ## Examples
38
129
 
39
- ### Minimal HTML example
130
+ ### Minimal search field
40
131
 
41
132
  ```html
42
133
  <hb-searchbar
43
134
  value=""
44
135
  searchlabel="Search"
45
- searchlist='[{"id":"1","text":"Suggestion"}]'
46
136
  ></hb-searchbar>
47
137
  ```
138
+
139
+ ### Suggestions with JSON `searchlist`
140
+
141
+ ```html
142
+ <hb-searchbar
143
+ value=""
144
+ searchlabel="Try a suggestion"
145
+ searchlist='[{"id":"1","text":"Documentation"},{"id":"2","text":"API reference"}]'
146
+ ></hb-searchbar>
147
+ ```
148
+
149
+ ### Multiline textarea mode
150
+
151
+ ```html
152
+ <hb-searchbar
153
+ value=""
154
+ searchlabel="Describe your query"
155
+ textarea="yes"
156
+ searchlist='[{"id":"1","text":"Example prompt"}]'
157
+ ></hb-searchbar>
158
+ ```
159
+
160
+ ### Disable preview, require two characters before input search
161
+
162
+ ```html
163
+ <hb-searchbar
164
+ value=""
165
+ disable_preview="yes"
166
+ minlength="2"
167
+ ></hb-searchbar>
168
+ ```
169
+
170
+ ### JavaScript: listen for `search` and `clear`
171
+
172
+ ```javascript
173
+ const el = document.querySelector("hb-searchbar");
174
+
175
+ el.addEventListener("search", (e) => {
176
+ const { input, by } = e.detail;
177
+ console.log("search", { input, by });
178
+ });
179
+
180
+ el.addEventListener("clear", (e) => {
181
+ console.log("cleared", e.detail.id);
182
+ });
183
+ ```
184
+
185
+ ## License
186
+
187
+ Package metadata references **Apache-2.0** (see `LICENSE.md` in the published package when consuming from npm).
package/manifest.json CHANGED
@@ -32,6 +32,9 @@
32
32
  },
33
33
  "input": {
34
34
  "type": "string"
35
+ },
36
+ "item": {
37
+ "$ref": "#/definitions/TSearchListItem"
35
38
  }
36
39
  },
37
40
  "required": [
@@ -46,6 +49,73 @@
46
49
  "clear"
47
50
  ],
48
51
  "type": "object"
52
+ },
53
+ "TSearchListItem": {
54
+ "additionalProperties": false,
55
+ "properties": {
56
+ "badge": {
57
+ "$ref": "#/definitions/TSearchListItemBadge"
58
+ },
59
+ "fixed": {
60
+ "type": "boolean"
61
+ },
62
+ "icon": {
63
+ "type": "string"
64
+ },
65
+ "id": {
66
+ "type": "string"
67
+ },
68
+ "number_of_results": {
69
+ "type": "number"
70
+ },
71
+ "tags": {
72
+ "items": {
73
+ "$ref": "#/definitions/TSearchListItemTag"
74
+ },
75
+ "type": "array"
76
+ },
77
+ "text": {
78
+ "type": "string"
79
+ },
80
+ "url": {
81
+ "type": "string"
82
+ }
83
+ },
84
+ "required": [
85
+ "text",
86
+ "id"
87
+ ],
88
+ "type": "object"
89
+ },
90
+ "TSearchListItemBadge": {
91
+ "additionalProperties": false,
92
+ "properties": {
93
+ "color": {
94
+ "type": "string"
95
+ },
96
+ "icon": {
97
+ "type": "string"
98
+ },
99
+ "text": {
100
+ "type": "string"
101
+ }
102
+ },
103
+ "type": "object"
104
+ },
105
+ "TSearchListItemTag": {
106
+ "additionalProperties": false,
107
+ "properties": {
108
+ "color": {
109
+ "type": "string"
110
+ },
111
+ "icon": {
112
+ "type": "string"
113
+ },
114
+ "text": {
115
+ "type": "string"
116
+ }
117
+ },
118
+ "type": "object"
49
119
  }
50
120
  }
51
121
  },
@@ -182,7 +252,7 @@
182
252
  }
183
253
  }
184
254
  },
185
- "description": "Search field with optional dropdown `searchlist` (id, text, icons, badges, tags, URLs). Configure `value`, `initial_value`, `searchlabel`, `textarea`, `minlength`, `disable_preview`, `disabled`, and CSS parts for the input and menu. Dispatches `search` and `clear`.",
255
+ "description": "Search field with optional dropdown `searchlist` (id, text, icons, badges, tags, URLs). Configure `value`, `searchlabel`, `textarea`, `minlength`, `disable_preview`, `disabled`, and CSS parts for the input and menu. Dispatches `search` (detail may include `item` when a suggestion is chosen) and `clear`.",
186
256
  "storybookArgs": {
187
257
  "initial_value": {
188
258
  "control": {
@@ -245,6 +315,78 @@
245
315
  },
246
316
  "styleSetup": {
247
317
  "vars": [
318
+ {
319
+ "name": "--bulma-primary",
320
+ "valueType": "color",
321
+ "defaultValue": "#00d1b2",
322
+ "description": "Focus ring, submit control hover, and highlighted suggestion rows."
323
+ },
324
+ {
325
+ "name": "--bulma-background",
326
+ "valueType": "color",
327
+ "defaultValue": "#ffffff",
328
+ "description": "Mixed into host strip and frosted defaults via `color-mix()`."
329
+ },
330
+ {
331
+ "name": "--bulma-scheme-main",
332
+ "valueType": "color",
333
+ "defaultValue": "#ffffff",
334
+ "description": "Dropdown panel mix target for open suggestions."
335
+ },
336
+ {
337
+ "name": "--bulma-border",
338
+ "valueType": "color",
339
+ "defaultValue": "#dbdbdb",
340
+ "description": "Field outline, dividers, and mix inputs for glass layers."
341
+ },
342
+ {
343
+ "name": "--bulma-border-weak",
344
+ "valueType": "color",
345
+ "defaultValue": "#ededed",
346
+ "description": "Softer separators inside the suggestion list."
347
+ },
348
+ {
349
+ "name": "--bulma-text",
350
+ "valueType": "color",
351
+ "defaultValue": "#363636",
352
+ "description": "Primary query text and list item copy."
353
+ },
354
+ {
355
+ "name": "--bulma-text-strong",
356
+ "valueType": "color",
357
+ "defaultValue": "#363636",
358
+ "description": "Emphasized suggestion titles."
359
+ },
360
+ {
361
+ "name": "--bulma-input-placeholder-color",
362
+ "valueType": "color",
363
+ "defaultValue": "rgba(54, 54, 54, 0.3)",
364
+ "description": "Placeholder tone for `searchlabel`."
365
+ },
366
+ {
367
+ "name": "--bulma-danger",
368
+ "valueType": "color",
369
+ "defaultValue": "#f14668",
370
+ "description": "Clear control accent."
371
+ },
372
+ {
373
+ "name": "--bulma-radius",
374
+ "valueType": "number",
375
+ "defaultValue": "0.375rem",
376
+ "description": "Field and dropdown corner radius."
377
+ },
378
+ {
379
+ "name": "--bulma-radius-small",
380
+ "valueType": "number",
381
+ "defaultValue": "0.25rem",
382
+ "description": "Inner chips / compact controls inside rows."
383
+ },
384
+ {
385
+ "name": "--bulma-dropdown-content-z",
386
+ "valueType": "number",
387
+ "defaultValue": "50",
388
+ "description": "Stacking order for the open suggestion panel."
389
+ },
248
390
  {
249
391
  "name": "--hb-searchbar-host-background",
250
392
  "valueType": "string",
@@ -285,19 +427,19 @@
285
427
  "parts": [
286
428
  {
287
429
  "name": "dropdown-menu",
288
- "description": "The dropdown menu"
430
+ "description": "Open suggestion list panel."
289
431
  },
290
432
  {
291
433
  "name": "search-input",
292
- "description": "The search input"
434
+ "description": "Native input or textarea surface."
293
435
  },
294
436
  {
295
437
  "name": "search-input-glass",
296
- "description": "Frosted glass layer behind the field (visible when the input/textarea is focused)"
438
+ "description": "Frosted backdrop behind the field while the input/textarea is focused."
297
439
  },
298
440
  {
299
441
  "name": "search-submit",
300
- "description": "The clickable search (magnifier) control"
442
+ "description": "In-field magnifier / submit control."
301
443
  }
302
444
  ]
303
445
  },
@@ -841,5 +983,5 @@
841
983
  "size": {},
842
984
  "iifePath": "main.iife.js",
843
985
  "repoName": "@htmlbricks/hb-searchbar",
844
- "version": "0.71.35"
986
+ "version": "0.71.37"
845
987
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@htmlbricks/hb-searchbar",
3
- "version": "0.71.35",
3
+ "version": "0.71.37",
4
4
  "contributors": [],
5
- "description": "Search field with optional dropdown `searchlist` (id, text, icons, badges, tags, URLs). Configure `value`, `initial_value`, `searchlabel`, `textarea`, `minlength`, `disable_preview`, `disabled`, and CSS parts for the input and menu. Dispatches `search` and `clear`.",
5
+ "description": "Search field with optional dropdown `searchlist` (id, text, icons, badges, tags, URLs). Configure `value`, `searchlabel`, `textarea`, `minlength`, `disable_preview`, `disabled`, and CSS parts for the input and menu. Dispatches `search` (detail may include `item` when a suggestion is chosen) and `clear`.",
6
6
  "licenses": [
7
7
  {
8
8
  "type": "Apache-2.0",
@@ -25,6 +25,10 @@ export type Component = {
25
25
  };
26
26
 
27
27
  export type Events = {
28
- search: { input: string; by: "button" | "input" | "searchlist" };
28
+ search: {
29
+ input: string;
30
+ by: "button" | "input" | "searchlist";
31
+ item?: TSearchListItem;
32
+ };
29
33
  clear: { id: string };
30
34
  };
@@ -30,6 +30,9 @@
30
30
  },
31
31
  "input": {
32
32
  "type": "string"
33
+ },
34
+ "item": {
35
+ "$ref": "#/definitions/TSearchListItem"
33
36
  }
34
37
  },
35
38
  "required": [
@@ -44,6 +47,73 @@
44
47
  "clear"
45
48
  ],
46
49
  "type": "object"
50
+ },
51
+ "TSearchListItem": {
52
+ "additionalProperties": false,
53
+ "properties": {
54
+ "badge": {
55
+ "$ref": "#/definitions/TSearchListItemBadge"
56
+ },
57
+ "fixed": {
58
+ "type": "boolean"
59
+ },
60
+ "icon": {
61
+ "type": "string"
62
+ },
63
+ "id": {
64
+ "type": "string"
65
+ },
66
+ "number_of_results": {
67
+ "type": "number"
68
+ },
69
+ "tags": {
70
+ "items": {
71
+ "$ref": "#/definitions/TSearchListItemTag"
72
+ },
73
+ "type": "array"
74
+ },
75
+ "text": {
76
+ "type": "string"
77
+ },
78
+ "url": {
79
+ "type": "string"
80
+ }
81
+ },
82
+ "required": [
83
+ "text",
84
+ "id"
85
+ ],
86
+ "type": "object"
87
+ },
88
+ "TSearchListItemBadge": {
89
+ "additionalProperties": false,
90
+ "properties": {
91
+ "color": {
92
+ "type": "string"
93
+ },
94
+ "icon": {
95
+ "type": "string"
96
+ },
97
+ "text": {
98
+ "type": "string"
99
+ }
100
+ },
101
+ "type": "object"
102
+ },
103
+ "TSearchListItemTag": {
104
+ "additionalProperties": false,
105
+ "properties": {
106
+ "color": {
107
+ "type": "string"
108
+ },
109
+ "icon": {
110
+ "type": "string"
111
+ },
112
+ "text": {
113
+ "type": "string"
114
+ }
115
+ },
116
+ "type": "object"
47
117
  }
48
118
  }
49
119
  }