@f-ewald/components 0.6.0 → 1.0.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 (75) hide show
  1. package/README.md +101 -44
  2. package/custom-elements.json +2570 -877
  3. package/dist/calendar-entry.d.ts +33 -0
  4. package/dist/calendar-entry.d.ts.map +1 -0
  5. package/dist/calendar-entry.js +64 -0
  6. package/dist/calendar-entry.js.map +1 -0
  7. package/dist/calendar-month.d.ts +67 -0
  8. package/dist/calendar-month.d.ts.map +1 -0
  9. package/dist/calendar-month.js +455 -0
  10. package/dist/calendar-month.js.map +1 -0
  11. package/dist/calendar-year.d.ts +43 -0
  12. package/dist/calendar-year.d.ts.map +1 -0
  13. package/dist/calendar-year.js +136 -0
  14. package/dist/calendar-year.js.map +1 -0
  15. package/dist/dropdown-button.d.ts +37 -0
  16. package/dist/dropdown-button.d.ts.map +1 -0
  17. package/dist/dropdown-button.js +219 -0
  18. package/dist/dropdown-button.js.map +1 -0
  19. package/dist/form-select.d.ts +27 -2
  20. package/dist/form-select.d.ts.map +1 -1
  21. package/dist/form-select.js +440 -27
  22. package/dist/form-select.js.map +1 -1
  23. package/dist/frame-box.d.ts +22 -0
  24. package/dist/frame-box.d.ts.map +1 -0
  25. package/dist/frame-box.js +68 -0
  26. package/dist/frame-box.js.map +1 -0
  27. package/dist/icon-button.d.ts +27 -0
  28. package/dist/icon-button.d.ts.map +1 -0
  29. package/dist/icon-button.js +83 -0
  30. package/dist/icon-button.js.map +1 -0
  31. package/dist/icons.d.ts +1 -0
  32. package/dist/icons.d.ts.map +1 -1
  33. package/dist/icons.js +1 -0
  34. package/dist/icons.js.map +1 -1
  35. package/dist/index.d.ts +6 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +6 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/map-circle.d.ts +3 -0
  40. package/dist/map-circle.d.ts.map +1 -1
  41. package/dist/map-circle.js +3 -0
  42. package/dist/map-circle.js.map +1 -1
  43. package/dist/mcp-server.d.ts +3 -0
  44. package/dist/mcp-server.d.ts.map +1 -0
  45. package/dist/mcp-server.js +82 -0
  46. package/dist/mcp-server.js.map +1 -0
  47. package/dist/popover-panel.d.ts +3 -0
  48. package/dist/popover-panel.d.ts.map +1 -1
  49. package/dist/popover-panel.js +11 -0
  50. package/dist/popover-panel.js.map +1 -1
  51. package/dist/tokens.css +4 -0
  52. package/dist/tokens.d.ts.map +1 -1
  53. package/dist/tokens.js +3 -0
  54. package/dist/tokens.js.map +1 -1
  55. package/dist/utils/calendar.d.ts +77 -0
  56. package/dist/utils/calendar.d.ts.map +1 -0
  57. package/dist/utils/calendar.js +135 -0
  58. package/dist/utils/calendar.js.map +1 -0
  59. package/docs/calendar-entry.md +53 -0
  60. package/docs/calendar-month.md +77 -0
  61. package/docs/calendar-year.md +53 -0
  62. package/docs/dropdown-button.md +61 -0
  63. package/docs/form-select.md +21 -3
  64. package/docs/frame-box.md +43 -0
  65. package/docs/icon-button.md +52 -0
  66. package/docs/map-circle.md +4 -0
  67. package/docs/mcp-evaluation.md +18 -11
  68. package/docs/popover-panel.md +5 -1
  69. package/llms.txt +194 -28
  70. package/package.json +19 -4
  71. package/dist/map-point.d.ts +0 -31
  72. package/dist/map-point.d.ts.map +0 -1
  73. package/dist/map-point.js +0 -83
  74. package/dist/map-point.js.map +0 -1
  75. package/docs/map-point.md +0 -44
@@ -0,0 +1,53 @@
1
+ # `<calendar-entry>`
2
+
3
+ Declarative metadata for one calendar event, consumed by a parent
4
+ `calendar-month` or `calendar-year`. Read-only/non-interactive; renders
5
+ nothing itself.
6
+
7
+ ## Install
8
+
9
+ ```js
10
+ import "@f-ewald/components/calendar-entry.js";
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```html
16
+ <calendar-entry
17
+ start="2026-07-10"
18
+ end="2026-07-18"
19
+ label="Vacation"
20
+ color="success"
21
+ >
22
+ <span slot="title">Vacation</span>
23
+ <span slot="detail">Out of office</span>
24
+ <span slot="detail">Road trip along the California coast with several scenic stops</span>
25
+ <span slot="footer">Return July 19 at 6 PM</span>
26
+ </calendar-entry>
27
+ ```
28
+
29
+ ## Attributes / properties
30
+
31
+ | Property | Attribute | Type | Default | Description |
32
+ | --- | --- | --- | --- | --- |
33
+ | `start` | `start` | `string` | `""` | Inclusive start date, `"YYYY-MM-DD"`. |
34
+ | `end` | `end` | `string` | `""` | Inclusive end date, `"YYYY-MM-DD"`. Falls back to `start` when unset (single-day entry). |
35
+ | `label` | `label` | `string` | `""` | Fallback title used when no `title` slot is provided. |
36
+ | `color` | `color` | `StatusPillColor` | `"neutral"` | Color variant, reusing `status-pill`'s palette. |
37
+ | `href` | `href` | `string | undefined` | `—` | Optional link target; the parent renders the entry as an `<a>` when set. |
38
+
39
+ ## Events
40
+
41
+ _None._
42
+
43
+ ## Slots
44
+
45
+ | Slot | Description |
46
+ | --- | --- |
47
+ | `title` | Plain-text title shown instead of the `label` fallback. |
48
+ | `detail` | Repeatable plain-text details rendered inside the shared body spanning all remaining days. |
49
+ | `footer` | Plain-text ending note pinned to the bottom of the shared body. |
50
+
51
+ ## CSS custom properties
52
+
53
+ _None._
@@ -0,0 +1,77 @@
1
+ # `<calendar-month>`
2
+
3
+ One month rendered as a top-to-bottom list of days — weekends and today
4
+ highlighted, with declarative `calendar-entry` children shown as colored
5
+ bars spanning the days they cover. An entry's title uses its first visible
6
+ day; every remaining visible day becomes one shared body for wrapped
7
+ details and an optional ending footer. Overlapping entries stack into
8
+ side-by-side lanes rather than being layered/hidden. Read-only.
9
+
10
+ Lanes are computed independently per instance, from only the entries
11
+ overlapping this month — an entry spanning a month boundary may therefore
12
+ land in a different lane index in the adjacent month's `calendar-month`.
13
+ This is an accepted v1 limitation: cross-month lane continuity would
14
+ require a shared parent (`calendar-year`) to assign lanes globally.
15
+
16
+ Entry attributes and slotted title/detail text are observed, so a
17
+ standalone month re-renders when consumers update declarative metadata.
18
+
19
+ ## Install
20
+
21
+ ```js
22
+ import "@f-ewald/components/calendar-month.js";
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ```html
28
+ <calendar-month year="2026" month="7">
29
+ <calendar-entry start="2026-07-10" end="2026-07-18" label="Vacation" color="success">
30
+ <span slot="title">Vacation</span>
31
+ <span slot="detail">Out of office</span>
32
+ <span slot="detail">Road trip along the California coast with several scenic stops</span>
33
+ <span slot="footer">Return July 19 at 6 PM</span>
34
+ </calendar-entry>
35
+ <calendar-entry start="2026-07-15" end="2026-07-20" label="Conference" color="warning" href="#conf">
36
+ <span slot="detail">Talks and workshops</span>
37
+ <span slot="footer">Closing keynote · July 20</span>
38
+ </calendar-entry>
39
+ </calendar-month>
40
+ ```
41
+
42
+ ## Attributes / properties
43
+
44
+ | Property | Attribute | Type | Default | Description |
45
+ | --- | --- | --- | --- | --- |
46
+ | `year` | `year` | `number` | `—` | Calendar year, e.g. `2026`. |
47
+ | `month` | `month` | `number` | `1` | Calendar month, 1-12 (January = 1). |
48
+
49
+ ## Events
50
+
51
+ _None._
52
+
53
+ ## Slots
54
+
55
+ | Slot | Description |
56
+ | --- | --- |
57
+ | `(default)` | Declarative `calendar-entry` elements to render for this month. |
58
+
59
+ ## CSS custom properties
60
+
61
+ | Custom property |
62
+ | --- |
63
+ | `--ui-border` |
64
+ | `--ui-danger` |
65
+ | `--ui-focus-ring` |
66
+ | `--ui-font` |
67
+ | `--ui-font-size` |
68
+ | `--ui-font-size-sm` |
69
+ | `--ui-font-size-xs` |
70
+ | `--ui-hover-overlay` |
71
+ | `--ui-primary` |
72
+ | `--ui-radius-sm` |
73
+ | `--ui-success` |
74
+ | `--ui-surface` |
75
+ | `--ui-surface-muted` |
76
+ | `--ui-text` |
77
+ | `--ui-text-muted` |
@@ -0,0 +1,53 @@
1
+ # `<calendar-year>`
2
+
3
+ A full year of `calendar-month` blocks, generated from declarative
4
+ `calendar-entry` children. Each entry is re-projected into the
5
+ `calendar-month` blocks it overlaps as a freshly-created `calendar-entry`
6
+ element — the original elements stay slotted here and are never moved,
7
+ since a DOM node can only have one parent. Read-only.
8
+
9
+ ## Install
10
+
11
+ ```js
12
+ import "@f-ewald/components/calendar-year.js";
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```html
18
+ <calendar-year year="2026">
19
+ <calendar-entry start="2026-01-28" end="2026-02-03" label="Offsite" color="primary" href="#offsite">
20
+ <span slot="detail">New York</span>
21
+ <span slot="detail">Team workshops</span>
22
+ <span slot="footer">Closing dinner Friday</span>
23
+ </calendar-entry>
24
+ <calendar-entry start="2026-03-05" end="2026-03-18" label="Product launch" color="success" href="#launch">
25
+ <span slot="detail">Coordinate the release across engineering, design, support, and marketing.</span>
26
+ <span slot="detail">Monitor adoption and production health throughout the rollout.</span>
27
+ <span slot="footer">Public launch · March 18 at 9 AM</span>
28
+ </calendar-entry>
29
+ <calendar-entry start="2026-07-10" end="2026-07-18" label="Vacation" color="success"></calendar-entry>
30
+ </calendar-year>
31
+ ```
32
+
33
+ ## Attributes / properties
34
+
35
+ | Property | Attribute | Type | Default | Description |
36
+ | --- | --- | --- | --- | --- |
37
+ | `year` | `year` | `number` | `—` | Calendar year to render all 12 months for, e.g. `2026`. |
38
+
39
+ ## Events
40
+
41
+ _None._
42
+
43
+ ## Slots
44
+
45
+ | Slot | Description |
46
+ | --- | --- |
47
+ | `(default)` | Declarative `calendar-entry` elements spanning the displayed year, re-projected into each month. |
48
+
49
+ ## CSS custom properties
50
+
51
+ | Custom property |
52
+ | --- |
53
+ | `--ui-font` |
@@ -0,0 +1,61 @@
1
+ # `<dropdown-button>`
2
+
3
+ A primary-styled button with a label and chevron that opens an anchored
4
+ menu of actions — essentially `form-select` minus "current value"
5
+ semantics: a menu, not a select. Use for a set of mutually exclusive
6
+ next-step actions (e.g. a failed task's Retry / Close / Backlog).
7
+
8
+ ## Install
9
+
10
+ ```js
11
+ import "@f-ewald/components/dropdown-button.js";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```html
17
+ <dropdown-button label="Resolve…"></dropdown-button>
18
+ <script type="module">
19
+ const dropdown = document.querySelector("dropdown-button");
20
+ dropdown.options = [
21
+ { value: "retry", label: "Retry" },
22
+ { value: "close", label: "Close" },
23
+ { value: "backlog", label: "Backlog" },
24
+ ];
25
+ dropdown.addEventListener("select", (e) => console.log(e.detail.value));
26
+ </script>
27
+ ```
28
+
29
+ ## Attributes / properties
30
+
31
+ | Property | Attribute | Type | Default | Description |
32
+ | --- | --- | --- | --- | --- |
33
+ | `label` | `label` | `string` | `""` | The trigger button's label. |
34
+ | `options` | _(JS property only)_ | `DropdownOption[]` | `[]` | The menu's actions. |
35
+ | `disabled` | `disabled` | `boolean` | `false` | Disables the trigger, preventing the menu from opening. |
36
+
37
+ ## Events
38
+
39
+ | Event | Description |
40
+ | --- | --- |
41
+ | `select` | Fired with `{ value: string }` when a menu item is picked. |
42
+
43
+ ## Slots
44
+
45
+ _None._
46
+
47
+ ## CSS custom properties
48
+
49
+ | Custom property |
50
+ | --- |
51
+ | `--ui-border` |
52
+ | `--ui-focus-ring` |
53
+ | `--ui-font` |
54
+ | `--ui-font-size-sm` |
55
+ | `--ui-primary` |
56
+ | `--ui-primary-hover` |
57
+ | `--ui-radius-sm` |
58
+ | `--ui-shadow` |
59
+ | `--ui-surface` |
60
+ | `--ui-surface-muted` |
61
+ | `--ui-text` |
@@ -6,6 +6,19 @@ a native `<select>` wherever consistent cross-browser styling and a
6
6
  `change` event carrying `{ value }` are wanted (e.g. a task's status
7
7
  picker).
8
8
 
9
+ The trigger fills its host's width (`justify-content: space-between`
10
+ pushes the chevron to the far edge), but the host itself stays
11
+ `display: inline-block` — so usages that never size the host (a filter
12
+ bar, a status picker) keep shrink-to-fit auto-width unchanged. To make an
13
+ instance full-width, size the host itself: `form-select { width: 100%; }`.
14
+
15
+ Set `searchable` to replace the button trigger with an editable combobox
16
+ that filters the predefined options by case-insensitive label infix. Typed
17
+ text is only a query: `value` changes exclusively when an actual option is
18
+ selected, and an uncommitted query is discarded when the list closes.
19
+ Each option may also provide a pre-rendered `icon` and square `iconSize`;
20
+ iconless options reserve no leading space.
21
+
9
22
  ## Install
10
23
 
11
24
  ```js
@@ -15,13 +28,17 @@ import "@f-ewald/components/form-select.js";
15
28
  ## Usage
16
29
 
17
30
  ```html
18
- <form-select label="Task state"></form-select>
31
+ <form-select label="Task state" searchable></form-select>
19
32
  <script type="module">
33
+ import { iconArrowPath, iconCheckCircle, iconListBullet } from "@f-ewald/components/icons.js";
34
+
20
35
  const select = document.querySelector("form-select");
21
36
  select.options = [
37
+ { value: "backlog", label: "Backlog", icon: iconListBullet(14), iconSize: 14 },
22
38
  { value: "open", label: "Open" },
23
- { value: "in_progress", label: "In progress" },
24
- { value: "done", label: "Done" },
39
+ { value: "in_progress", label: "In progress", icon: iconArrowPath(16), iconSize: 16 },
40
+ { value: "review", label: "Needs review" },
41
+ { value: "done", label: "Done", icon: iconCheckCircle(16), iconSize: 16 },
25
42
  ];
26
43
  select.value = "open";
27
44
  select.addEventListener("change", (e) => console.log(e.detail.value));
@@ -36,6 +53,7 @@ import "@f-ewald/components/form-select.js";
36
53
  | `value` | `value` | `string` | `""` | Currently selected value; must match one of `options[].value`. |
37
54
  | `label` | `label` | `string` | `""` | `aria-label` applied to the trigger button. |
38
55
  | `disabled` | `disabled` | `boolean` | `false` | Disables the trigger, preventing the popover from opening. |
56
+ | `searchable` | `searchable` | `boolean` | `false` | Enables editable, case-insensitive infix filtering by option label. Typed text never becomes the selected `value`. |
39
57
 
40
58
  ## Events
41
59
 
@@ -0,0 +1,43 @@
1
+ # `<frame-box>`
2
+
3
+ A titled frame around a slot: a gray border with a small uppercase,
4
+ muted label overlapping the top edge (fieldset/legend-style). Generic —
5
+ the label text is entirely up to the consumer (e.g. "Debug" to visually
6
+ fence off dev-only chrome from the product UI).
7
+
8
+ ## Install
9
+
10
+ ```js
11
+ import "@f-ewald/components/frame-box.js";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```html
17
+ <frame-box label="Debug">
18
+ Framed content goes here.
19
+ </frame-box>
20
+ ```
21
+
22
+ ## Attributes / properties
23
+
24
+ | Property | Attribute | Type | Default | Description |
25
+ | --- | --- | --- | --- | --- |
26
+ | `label` | `label` | `string` | `""` | The overlapping title label, e.g. "Debug". |
27
+
28
+ ## Events
29
+
30
+ _None._
31
+
32
+ ## Slots
33
+
34
+ _None._
35
+
36
+ ## CSS custom properties
37
+
38
+ | Custom property |
39
+ | --- |
40
+ | `--ui-border` |
41
+ | `--ui-radius-sm` |
42
+ | `--ui-surface` |
43
+ | `--ui-text-muted` |
@@ -0,0 +1,52 @@
1
+ # `<icon-button>`
2
+
3
+ A borderless button wrapping a passed-in icon, with a rounded
4
+ hover-highlight background. Use for a low-emphasis affordance next to
5
+ content it acts on (e.g. an "Edit" pencil at the end of a table row)
6
+ where a bordered `ui-button` would be too heavy.
7
+
8
+ ## Install
9
+
10
+ ```js
11
+ import "@f-ewald/components/icon-button.js";
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```html
17
+ <icon-button label="Edit"></icon-button>
18
+ <script type="module">
19
+ import { iconPencil } from "@f-ewald/components/icons.js";
20
+ const btn = document.querySelector("icon-button");
21
+ btn.icon = iconPencil(16);
22
+ btn.addEventListener("click", () => console.log("edit clicked"));
23
+ </script>
24
+ ```
25
+
26
+ ## Attributes / properties
27
+
28
+ | Property | Attribute | Type | Default | Description |
29
+ | --- | --- | --- | --- | --- |
30
+ | `icon` | _(JS property only)_ | `TemplateResult | null` | `null` | Pre-rendered icon template, e.g. `iconPencil(16)` from this package's icon set. |
31
+ | `label` | `label` | `string` | `""` | Required accessible label, applied as `aria-label`/`title`. |
32
+ | `disabled` | `disabled` | `boolean` | `false` | Disables the button and dims it. |
33
+
34
+ ## Events
35
+
36
+ | Event | Description |
37
+ | --- | --- |
38
+ | `click` | Native click, bubbling as usual — listen on the element itself. |
39
+
40
+ ## Slots
41
+
42
+ _None._
43
+
44
+ ## CSS custom properties
45
+
46
+ | Custom property |
47
+ | --- |
48
+ | `--ui-focus-ring` |
49
+ | `--ui-radius-sm` |
50
+ | `--ui-surface-muted` |
51
+ | `--ui-text` |
52
+ | `--ui-text-muted` |
@@ -5,6 +5,9 @@ outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't
5
5
  need to visually "point" at their exact coordinate. Purely a visual
6
6
  primitive — it has no `mapbox-gl` (or any mapping library) dependency;
7
7
  the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.
8
+ It can also replace the former `<map-point>` dense-layer primitive: use
9
+ `size="14" ring-width="3"`, leave the slot empty, and rasterize one marker
10
+ per color for use as a map `icon-image`.
8
11
 
9
12
  ## Install
10
13
 
@@ -16,6 +19,7 @@ import "@f-ewald/components/map-circle.js";
16
19
 
17
20
  ```html
18
21
  <map-circle color="#6b7280"></map-circle>
22
+ <map-circle color="#0099D8" size="14" ring-width="3"></map-circle>
19
23
  <map-circle color="#1a73e8" size="24" ring-width="5" highlighted>1</map-circle>
20
24
  ```
21
25
 
@@ -1,31 +1,38 @@
1
1
  # MCP server evaluation
2
2
 
3
- **Recommendation: do not build an MCP server for this package now.**
3
+ **Update (0.6.0 era, 34 components): built.** The catalog crossed the ~30+
4
+ revisit threshold below, so the upgrade path described here was implemented
5
+ as `src/mcp-server.ts`. See the "MCP server" section in the root `CLAUDE.md`
6
+ for the current tools, build step, and how consuming projects wire it up.
7
+ The original evaluation is kept below for the reasoning that justified
8
+ waiting until this point.
9
+
10
+ ## Original recommendation (superseded): do not build an MCP server yet
4
11
 
5
12
  ## Rationale
6
13
 
7
- The component catalog is small (14 tags). `llms.txt` ships in the npm
14
+ The component catalog was small (14 tags). `llms.txt` ships in the npm
8
15
  package and is fetchable directly from unpkg or GitHub raw, so any LLM or
9
16
  agent can load the full API surface — every component's attributes,
10
17
  properties, events, slots, tokens, and a usage example — in one small file,
11
18
  with no server, process, or additional versioning/packaging burden. An MCP
12
19
  server would duplicate that same data behind a stdio process that needs its
13
20
  own install, auth-free-but-still-a-process lifecycle, and release cadence
14
- kept in sync with the package — for zero functional gain at this scale.
21
+ kept in sync with the package — for zero functional gain at that scale.
15
22
 
16
- ## When to revisit
23
+ ## When to revisit (met)
17
24
 
18
25
  - The catalog grows past a size where `llms.txt` stops being comfortable to
19
- load into a single context window (rule of thumb: ~30+ components).
26
+ load into a single context window (rule of thumb: ~30+ components).
27
+ **met at 34 components.**
20
28
  - Consumers want live search, fuzzy matching, or filtered/paginated results
21
29
  instead of "load everything."
22
30
  - Consumers want examples or docs that go beyond what's derivable from
23
31
  `custom-elements.json` (e.g. runnable playground snippets, live preview).
24
32
 
25
- ## Upgrade path
33
+ ## Upgrade path (implemented)
26
34
 
27
- If/when it's warranted, a thin stdio MCP server exposing two tools —
28
- `list_components` and `get_component_docs(tag)` — backed by the same
29
- `custom-elements.json` this package already generates and ships. No new
30
- data source would be needed; the server would just be a different transport
31
- over data that already exists.
35
+ A thin stdio MCP server exposing two tools — `list_components` and
36
+ `get_component_docs(tag)` — backed by the same `custom-elements.json` this
37
+ package already generates and ships. No new data source was needed; the
38
+ server is just a different transport over data that already existed.
@@ -48,7 +48,11 @@ import "@f-ewald/components/popover-panel.js";
48
48
 
49
49
  ## Slots
50
50
 
51
- _None._
51
+ | Slot | Description |
52
+ | --- | --- |
53
+ | `(default)` | Popover body content. |
54
+ | `title` | Overrides the plain `heading` text with custom markup. |
55
+ | `actions` | Extra header controls (e.g. an icon+label link) rendered between the title and the close button. |
52
56
 
53
57
  ## CSS custom properties
54
58