@f-ewald/components 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +27 -0
  2. package/custom-elements.json +3290 -835
  3. package/dist/chat-message.d.ts +39 -0
  4. package/dist/chat-message.d.ts.map +1 -0
  5. package/dist/chat-message.js +155 -0
  6. package/dist/chat-message.js.map +1 -0
  7. package/dist/data-table.d.ts +39 -0
  8. package/dist/data-table.d.ts.map +1 -0
  9. package/dist/data-table.js +119 -0
  10. package/dist/data-table.js.map +1 -0
  11. package/dist/editable-text.d.ts +52 -0
  12. package/dist/editable-text.d.ts.map +1 -0
  13. package/dist/editable-text.js +224 -0
  14. package/dist/editable-text.js.map +1 -0
  15. package/dist/form-select.d.ts +40 -0
  16. package/dist/form-select.d.ts.map +1 -0
  17. package/dist/form-select.js +236 -0
  18. package/dist/form-select.js.map +1 -0
  19. package/dist/gallery-item-variant.d.ts +21 -0
  20. package/dist/gallery-item-variant.d.ts.map +1 -0
  21. package/dist/gallery-item-variant.js +44 -0
  22. package/dist/gallery-item-variant.js.map +1 -0
  23. package/dist/gallery-item.d.ts +28 -0
  24. package/dist/gallery-item.d.ts.map +1 -0
  25. package/dist/gallery-item.js +54 -0
  26. package/dist/gallery-item.js.map +1 -0
  27. package/dist/icons.d.ts +7 -0
  28. package/dist/icons.d.ts.map +1 -1
  29. package/dist/icons.js +7 -0
  30. package/dist/icons.js.map +1 -1
  31. package/dist/index.d.ts +13 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +13 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/live-timer.d.ts +31 -0
  36. package/dist/live-timer.d.ts.map +1 -0
  37. package/dist/live-timer.js +78 -0
  38. package/dist/live-timer.js.map +1 -0
  39. package/dist/photo-gallery.d.ts +117 -0
  40. package/dist/photo-gallery.d.ts.map +1 -0
  41. package/dist/photo-gallery.js +620 -0
  42. package/dist/photo-gallery.js.map +1 -0
  43. package/dist/popover-panel.d.ts +34 -0
  44. package/dist/popover-panel.d.ts.map +1 -0
  45. package/dist/popover-panel.js +173 -0
  46. package/dist/popover-panel.js.map +1 -0
  47. package/dist/status-pill.d.ts +24 -0
  48. package/dist/status-pill.d.ts.map +1 -0
  49. package/dist/status-pill.js +101 -0
  50. package/dist/status-pill.js.map +1 -0
  51. package/dist/tile-grid.d.ts +32 -0
  52. package/dist/tile-grid.d.ts.map +1 -0
  53. package/dist/tile-grid.js +102 -0
  54. package/dist/tile-grid.js.map +1 -0
  55. package/dist/tokens.css +39 -0
  56. package/dist/tokens.d.ts +28 -3
  57. package/dist/tokens.d.ts.map +1 -1
  58. package/dist/tokens.js +42 -43
  59. package/dist/tokens.js.map +1 -1
  60. package/dist/user-avatar.d.ts +5 -2
  61. package/dist/user-avatar.d.ts.map +1 -1
  62. package/dist/user-avatar.js +22 -6
  63. package/dist/user-avatar.js.map +1 -1
  64. package/dist/utils/duration.d.ts +12 -0
  65. package/dist/utils/duration.d.ts.map +1 -0
  66. package/dist/utils/duration.js +27 -0
  67. package/dist/utils/duration.js.map +1 -0
  68. package/docs/chat-message.md +59 -0
  69. package/docs/data-table.md +63 -0
  70. package/docs/editable-text.md +51 -0
  71. package/docs/form-select.md +64 -0
  72. package/docs/gallery-item-variant.md +37 -0
  73. package/docs/gallery-item.md +47 -0
  74. package/docs/live-timer.md +39 -0
  75. package/docs/photo-gallery.md +77 -0
  76. package/docs/popover-panel.md +66 -0
  77. package/docs/status-pill.md +43 -0
  78. package/docs/tile-grid.md +58 -0
  79. package/docs/user-avatar.md +1 -1
  80. package/llms.txt +280 -1
  81. package/package.json +1 -1
package/llms.txt CHANGED
@@ -104,6 +104,30 @@ Example:
104
104
  </script>
105
105
  ```
106
106
 
107
+ ## <chat-message>
108
+
109
+ One conversation entry in a chat-style activity feed. Tool calls and
110
+ "thinking" traces are variants of this component rather than separate
111
+ ones — they share the same header, collapse behavior, and body card as a
112
+ normal message, just dimmed and collapsible with an always-visible summary.
113
+
114
+ Import: `import "@f-ewald/components/chat-message.js";`
115
+
116
+ Properties: `role` (attribute `role`) : ChatMessageRole, default "agent"; `variant` (attribute `variant`) : ChatMessageVariant, default "normal"; `author` (attribute `author`) : string, default ""; `timestamp` (attribute `timestamp`) : string | null, default null; `summary` (attribute `summary`) : string, default ""; `collapsible` (attribute `collapsible`) : boolean, default false; `collapsed` (attribute `collapsed`) : boolean, default false
117
+ Events: `toggle`
118
+ CSS custom properties: `--ui-border`, `--ui-font`, `--ui-font-size`, `--ui-primary`, `--ui-radius`, `--ui-surface`, `--ui-text`, `--ui-text-muted`
119
+
120
+ Example:
121
+ ```html
122
+ <chat-message role="user" author="Freddy" timestamp="2026-07-19T12:00:00Z">
123
+ Write notes.md containing a haiku.
124
+ </chat-message>
125
+ <chat-message role="agent" variant="tool" collapsible collapsed summary='file_write · {"filename": "notes.md"}'>
126
+ directory: .
127
+ filename: notes.md
128
+ </chat-message>
129
+ ```
130
+
107
131
  ## <confirm-dialog>
108
132
 
109
133
  Reusable confirmation dialog: overlay + centered card with a slotted body,
@@ -144,6 +168,40 @@ Example:
144
168
  <copy-link-button value="https://example.com/listing/42" label="Copy listing link"></copy-link-button>
145
169
  ```
146
170
 
171
+ ## <data-table>
172
+
173
+ A generic, presentational table shell: renders a `<thead>` from `columns`
174
+ and one `<tr>` per entry in `rows`, with each cell's content produced by
175
+ `renderCell` (default: plain property lookup on the row object). Knows
176
+ nothing about what a "row" means — callers own the data shape entirely.
177
+
178
+ Optional `rowHref` makes whole rows clickable (navigating via `location.hash`),
179
+ without hijacking clicks on nested interactive elements (links/buttons) a
180
+ cell's rendered content might contain.
181
+
182
+ Import: `import "@f-ewald/components/data-table.js";`
183
+
184
+ Properties: `columns` (JS property only) : DataTableColumn[], default []; `rows` (JS property only) : unknown[], default []; `rowKey` (JS property only) : (row: unknown, index: number) => string | number, default —; `renderCell` (JS property only) : (row: unknown, key: string) => unknown, default —; `rowHref` (JS property only) : ((row: unknown) => string | null) | null, default null
185
+ Events: none
186
+ CSS custom properties: `--ui-border`, `--ui-font`, `--ui-font-size-sm`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`
187
+
188
+ Example:
189
+ ```html
190
+ <data-table></data-table>
191
+ <script type="module">
192
+ const table = document.querySelector("data-table");
193
+ table.columns = [
194
+ { key: "title", label: "Title" },
195
+ { key: "state", label: "State" },
196
+ ];
197
+ table.rows = [
198
+ { id: "tsk_1", title: "Write onboarding docs", state: "Backlog" },
199
+ { id: "tsk_2", title: "Fix the login bug", state: "Done" },
200
+ ];
201
+ table.rowHref = (row) => `#/tasks/${row.id}`;
202
+ </script>
203
+ ```
204
+
147
205
  ## <distance-value>
148
206
 
149
207
  Inline distance display. Renders miles/feet or km/m, switching units at
@@ -188,6 +246,114 @@ Example:
188
246
  </script>
189
247
  ```
190
248
 
249
+ ## <editable-text>
250
+
251
+ Jira/GitHub-style click-to-edit text: a display span that turns into an
252
+ `<input>` (or auto-growing `<textarea>` when `multiline`) on click. The
253
+ input/textarea inherits the host's font, so a title wrapped in an `<h1>`
254
+ edits at title size.
255
+
256
+ Import: `import "@f-ewald/components/editable-text.js";`
257
+
258
+ Properties: `value` (attribute `value`) : string, default ""; `multiline` (attribute `multiline`) : boolean, default false; `placeholder` (attribute `placeholder`) : string, default ""; `readonly` (attribute `readonly`) : boolean, default false; `label` (attribute `label`) : string, default ""
259
+ Events: `change`
260
+ CSS custom properties: `--ui-border`, `--ui-focus-ring`, `--ui-primary`, `--ui-radius-sm`, `--ui-surface`, `--ui-surface-muted`, `--ui-text-muted`
261
+
262
+ Example:
263
+ ```html
264
+ <editable-text value="Write the quarterly report" label="Title"></editable-text>
265
+ <editable-text multiline placeholder="Add a description…" label="Description"></editable-text>
266
+ ```
267
+
268
+ ## <form-select>
269
+
270
+ A styled dropdown select: a trigger button showing the current option's
271
+ label, opening a listbox popover on click. Drop-in generic replacement for
272
+ a native `<select>` wherever consistent cross-browser styling and a
273
+ `change` event carrying `{ value }` are wanted (e.g. a task's status
274
+ picker).
275
+
276
+ Import: `import "@f-ewald/components/form-select.js";`
277
+
278
+ Properties: `options` (JS property only) : SelectOption[], default []; `value` (attribute `value`) : string, default ""; `label` (attribute `label`) : string, default ""; `disabled` (attribute `disabled`) : boolean, default false
279
+ Events: `change`
280
+ CSS custom properties: `--ui-border`, `--ui-focus-ring`, `--ui-font`, `--ui-font-size-sm`, `--ui-primary`, `--ui-radius-sm`, `--ui-shadow`, `--ui-surface`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`
281
+
282
+ Example:
283
+ ```html
284
+ <form-select label="Task state"></form-select>
285
+ <script type="module">
286
+ const select = document.querySelector("form-select");
287
+ select.options = [
288
+ { value: "open", label: "Open" },
289
+ { value: "in_progress", label: "In progress" },
290
+ { value: "done", label: "Done" },
291
+ ];
292
+ select.value = "open";
293
+ select.addEventListener("change", (e) => console.log(e.detail.value));
294
+ </script>
295
+ ```
296
+
297
+ ## <gallery-item>
298
+
299
+ Declarative image metadata consumed by a parent `photo-gallery`.
300
+
301
+ Import: `import "@f-ewald/components/gallery-item.js";`
302
+
303
+ Properties: `src` (attribute `src`) : string, default ""; `alt` (attribute `alt`) : string, default ""; `caption` (attribute `caption`) : string | undefined, default —; `variants` (JS property only) : GalleryItemVariant[], default —
304
+ Events: none
305
+ CSS custom properties: none
306
+
307
+ Example:
308
+ ```html
309
+ <gallery-item
310
+ src="/photos/coast.jpg"
311
+ alt="Rocky California coastline"
312
+ caption="California coast"
313
+ >
314
+ <gallery-item-variant
315
+ media="(max-width: 640px)"
316
+ srcset="/photos/coast-portrait.jpg"
317
+ ></gallery-item-variant>
318
+ </gallery-item>
319
+ ```
320
+
321
+ ## <gallery-item-variant>
322
+
323
+ Responsive image source metadata for a parent `gallery-item`.
324
+
325
+ Import: `import "@f-ewald/components/gallery-item-variant.js";`
326
+
327
+ Properties: `media` (attribute `media`) : string | undefined, default —; `srcset` (attribute `srcset`) : string, default ""
328
+ Events: none
329
+ CSS custom properties: none
330
+
331
+ Example:
332
+ ```html
333
+ <gallery-item-variant
334
+ media="(max-width: 640px)"
335
+ srcset="/photos/coast-portrait.jpg"
336
+ ></gallery-item-variant>
337
+ ```
338
+
339
+ ## <live-timer>
340
+
341
+ Per-second ticking count-up timer, e.g. a live "running for 12s" or
342
+ "Sleeping for 3 seconds" indicator. Renders nothing while `since` is unset
343
+ or unparseable.
344
+
345
+ Import: `import "@f-ewald/components/live-timer.js";`
346
+
347
+ Properties: `since` (attribute `since`) : string | null, default null; `format` (attribute `format`) : DurationFormat, default "seconds"; `prefix` (attribute `prefix`) : string, default ""; `suffix` (attribute `suffix`) : string, default ""
348
+ Events: none
349
+ CSS custom properties: none
350
+
351
+ Example:
352
+ ```html
353
+ <live-timer since="2026-07-19T12:00:00Z" prefix="Sleeping for "></live-timer>
354
+ <live-timer since="2026-07-19T12:00:00Z" format="compact" prefix="running for "></live-timer>
355
+ ```
356
+
191
357
  ## <map-circle>
192
358
 
193
359
  A plain circular map marker: a light-to-dark gradient fill with a white
@@ -273,6 +439,72 @@ Example:
273
439
  </script>
274
440
  ```
275
441
 
442
+ ## <photo-gallery>
443
+
444
+ Responsive, accessible image carousel composed from declarative
445
+ `gallery-item` children.
446
+
447
+ Import: `import "@f-ewald/components/photo-gallery.js";`
448
+
449
+ Properties: `currentIndex` (attribute `current-index`) : number, default 0; `delay` (attribute `delay`) : number, default 0; `showControls` (attribute `show-controls`) : boolean, default true; `showCounter` (attribute `show-counter`) : boolean, default false; `showIndicators` (attribute `show-indicators`) : boolean, default false; `showAutoplayControl` (attribute `show-autoplay-control`) : boolean, default true; `paused` (attribute `paused`) : boolean, default false; `aspectRatio` (attribute `aspect-ratio`) : string, default "16 / 9"; `objectFit` (attribute `object-fit`) : PhotoGalleryObjectFit, default "cover"
450
+ Events: `slide-change`
451
+ CSS custom properties: `--ui-border`, `--ui-focus-ring`, `--ui-font`, `--ui-font-size`, `--ui-font-size-sm`, `--ui-overlay`, `--ui-primary`, `--ui-radius`, `--ui-radius-sm`, `--ui-surface`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`
452
+
453
+ Example:
454
+ ```html
455
+ <photo-gallery delay="5000" show-counter show-indicators>
456
+ <gallery-item
457
+ src="/photos/coast.jpg"
458
+ alt="Rocky California coastline"
459
+ caption="California coast"
460
+ >
461
+ <gallery-item-variant
462
+ media="(max-width: 640px)"
463
+ srcset="/photos/coast-portrait.jpg"
464
+ ></gallery-item-variant>
465
+ </gallery-item>
466
+ <gallery-item src="/photos/bridge.jpg" alt="Golden Gate Bridge"></gallery-item>
467
+ </photo-gallery>
468
+ <script type="module">
469
+ document.querySelector("photo-gallery").addEventListener("slide-change", (event) => {
470
+ console.log(event.detail.currentIndex);
471
+ });
472
+ </script>
473
+ ```
474
+
475
+ ## <popover-panel>
476
+
477
+ Generic anchored popover shell: a floating card positioned relative to its
478
+ nearest `position: relative` ancestor (place it next to its trigger button
479
+ inside such a wrapper), as opposed to `slide-panel`'s fixed screen-edge
480
+ drawer. Closes on outside click or Escape. Header chrome and close button
481
+ match `slide-panel`'s API (`heading`, `panel-close`) so either can be
482
+ swapped in for the other with no consumer-side changes beyond the wrapper.
483
+
484
+ Set `centered` to render as a screen-centered modal with a translucent
485
+ backdrop instead of the default anchored placement.
486
+
487
+ Import: `import "@f-ewald/components/popover-panel.js";`
488
+
489
+ Properties: `open` (attribute `open`) : boolean, default false; `heading` (attribute `heading`) : string, default ""; `centered` (attribute `centered`) : boolean, default false
490
+ Events: `panel-close`
491
+ CSS custom properties: `--ui-border`, `--ui-font`, `--ui-font-size`, `--ui-radius`, `--ui-radius-sm`, `--ui-shadow-lg`, `--ui-surface`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`
492
+
493
+ Example:
494
+ ```html
495
+ <div style="position: relative; display: inline-block;">
496
+ <button id="new-task-btn">New task</button>
497
+ <popover-panel heading="New task">
498
+ Popover body content goes here.
499
+ </popover-panel>
500
+ </div>
501
+ <script type="module">
502
+ const popover = document.querySelector("popover-panel");
503
+ document.querySelector("#new-task-btn").addEventListener("click", () => (popover.open = true));
504
+ popover.addEventListener("panel-close", () => (popover.open = false));
505
+ </script>
506
+ ```
507
+
276
508
  ## <price-history-chart>
277
509
 
278
510
  D3-powered SVG line chart for property price history.
@@ -447,6 +679,53 @@ Example:
447
679
  <stat-meter label="GPU" percent="88" color="#dc2626"></stat-meter>
448
680
  ```
449
681
 
682
+ ## <status-pill>
683
+
684
+ Small colored status pill, optionally with a spinning icon — for task/run
685
+ states ("Open", "Blocked", "Done") and live-activity indicators ("Running").
686
+
687
+ Import: `import "@f-ewald/components/status-pill.js";`
688
+
689
+ Properties: `label` (attribute `label`) : string, default ""; `color` (attribute `color`) : StatusPillColor, default "neutral"; `spinner` (attribute `spinner`) : boolean, default false
690
+ Events: none
691
+ CSS custom properties: `--ui-danger`, `--ui-font`, `--ui-primary`, `--ui-success`, `--ui-text-muted`
692
+
693
+ Example:
694
+ ```html
695
+ <status-pill label="Running" color="primary" spinner></status-pill>
696
+ <status-pill label="Blocked" color="danger"></status-pill>
697
+ ```
698
+
699
+ ## <tile-grid>
700
+
701
+ A generic, presentational grid shell: renders one bordered card per entry
702
+ in `items`, with each tile's content produced by `renderTile` (default:
703
+ stringify). Knows nothing about what an "item" means — callers own the
704
+ data shape entirely. Modeled directly on `data-table`'s headless pattern.
705
+
706
+ Optional `itemHref` makes whole tiles clickable (navigating via
707
+ `location.hash`), without hijacking clicks on nested interactive elements
708
+ (links/buttons) a tile's rendered content might contain.
709
+
710
+ Import: `import "@f-ewald/components/tile-grid.js";`
711
+
712
+ Properties: `items` (JS property only) : unknown[], default []; `itemKey` (JS property only) : (item: unknown, index: number) => string | number, default —; `renderTile` (JS property only) : (item: unknown) => unknown, default —; `itemHref` (JS property only) : ((item: unknown) => string | null) | null, default null
713
+ Events: none
714
+ CSS custom properties: `--ui-border`, `--ui-font`, `--ui-font-size-sm`, `--ui-radius`, `--ui-surface-muted`, `--ui-text`
715
+
716
+ Example:
717
+ ```html
718
+ <tile-grid></tile-grid>
719
+ <script type="module">
720
+ const grid = document.querySelector("tile-grid");
721
+ grid.items = [
722
+ { name: "notes.txt" },
723
+ { name: "photo.jpg" },
724
+ ];
725
+ grid.renderTile = (item) => item.name;
726
+ </script>
727
+ ```
728
+
450
729
  ## <toast-notification>
451
730
 
452
731
  Fixed-position stack of dismissible notifications, anchored top-right
@@ -514,7 +793,7 @@ circle.
514
793
 
515
794
  Import: `import "@f-ewald/components/user-avatar.js";`
516
795
 
517
- Properties: `src` (attribute `src`) : string | null, default null; `name` (attribute `name`) : string | null, default null; `size` (attribute `size`) : number, default 32
796
+ Properties: `src` (attribute `src`) : string | null, default null; `name` (attribute `name`) : string | null, default null; `size` (attribute `size`) : string | number, default 32
518
797
  Events: none
519
798
  CSS custom properties: `--ui-font`, `--ui-primary`
520
799
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@f-ewald/components",
3
3
  "private": false,
4
- "version": "0.5.0",
4
+ "version": "0.6.0",
5
5
  "description": "A collection of universally usable web components for various tasks.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",