@f-ewald/components 0.7.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 (46) hide show
  1. package/README.md +70 -47
  2. package/custom-elements.json +2236 -966
  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/form-select.d.ts +21 -2
  16. package/dist/form-select.d.ts.map +1 -1
  17. package/dist/form-select.js +431 -27
  18. package/dist/form-select.js.map +1 -1
  19. package/dist/index.d.ts +3 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/map-circle.d.ts +3 -0
  24. package/dist/map-circle.d.ts.map +1 -1
  25. package/dist/map-circle.js +3 -0
  26. package/dist/map-circle.js.map +1 -1
  27. package/dist/tokens.css +4 -0
  28. package/dist/tokens.d.ts.map +1 -1
  29. package/dist/tokens.js +3 -0
  30. package/dist/tokens.js.map +1 -1
  31. package/dist/utils/calendar.d.ts +77 -0
  32. package/dist/utils/calendar.d.ts.map +1 -0
  33. package/dist/utils/calendar.js +135 -0
  34. package/dist/utils/calendar.js.map +1 -0
  35. package/docs/calendar-entry.md +53 -0
  36. package/docs/calendar-month.md +77 -0
  37. package/docs/calendar-year.md +53 -0
  38. package/docs/form-select.md +15 -3
  39. package/docs/map-circle.md +4 -0
  40. package/llms.txt +117 -28
  41. package/package.json +10 -2
  42. package/dist/map-point.d.ts +0 -31
  43. package/dist/map-point.d.ts.map +0 -1
  44. package/dist/map-point.js +0 -83
  45. package/dist/map-point.js.map +0 -1
  46. 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` |
@@ -12,6 +12,13 @@ pushes the chevron to the far edge), but the host itself stays
12
12
  bar, a status picker) keep shrink-to-fit auto-width unchanged. To make an
13
13
  instance full-width, size the host itself: `form-select { width: 100%; }`.
14
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
+
15
22
  ## Install
16
23
 
17
24
  ```js
@@ -21,13 +28,17 @@ import "@f-ewald/components/form-select.js";
21
28
  ## Usage
22
29
 
23
30
  ```html
24
- <form-select label="Task state"></form-select>
31
+ <form-select label="Task state" searchable></form-select>
25
32
  <script type="module">
33
+ import { iconArrowPath, iconCheckCircle, iconListBullet } from "@f-ewald/components/icons.js";
34
+
26
35
  const select = document.querySelector("form-select");
27
36
  select.options = [
37
+ { value: "backlog", label: "Backlog", icon: iconListBullet(14), iconSize: 14 },
28
38
  { value: "open", label: "Open" },
29
- { value: "in_progress", label: "In progress" },
30
- { 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 },
31
42
  ];
32
43
  select.value = "open";
33
44
  select.addEventListener("change", (e) => console.log(e.detail.value));
@@ -42,6 +53,7 @@ import "@f-ewald/components/form-select.js";
42
53
  | `value` | `value` | `string` | `""` | Currently selected value; must match one of `options[].value`. |
43
54
  | `label` | `label` | `string` | `""` | `aria-label` applied to the trigger button. |
44
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`. |
45
57
 
46
58
  ## Events
47
59
 
@@ -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
 
package/llms.txt CHANGED
@@ -104,6 +104,104 @@ Example:
104
104
  </script>
105
105
  ```
106
106
 
107
+ ## <calendar-entry>
108
+
109
+ Declarative metadata for one calendar event, consumed by a parent
110
+ `calendar-month` or `calendar-year`. Read-only/non-interactive; renders
111
+ nothing itself.
112
+
113
+ Import: `import "@f-ewald/components/calendar-entry.js";`
114
+
115
+ Properties: `start` (attribute `start`) : string, default ""; `end` (attribute `end`) : string, default ""; `label` (attribute `label`) : string, default ""; `color` (attribute `color`) : StatusPillColor, default "neutral"; `href` (attribute `href`) : string | undefined, default —
116
+ Events: none
117
+ CSS custom properties: none
118
+
119
+ Example:
120
+ ```html
121
+ <calendar-entry
122
+ start="2026-07-10"
123
+ end="2026-07-18"
124
+ label="Vacation"
125
+ color="success"
126
+ >
127
+ <span slot="title">Vacation</span>
128
+ <span slot="detail">Out of office</span>
129
+ <span slot="detail">Road trip along the California coast with several scenic stops</span>
130
+ <span slot="footer">Return July 19 at 6 PM</span>
131
+ </calendar-entry>
132
+ ```
133
+
134
+ ## <calendar-month>
135
+
136
+ One month rendered as a top-to-bottom list of days — weekends and today
137
+ highlighted, with declarative `calendar-entry` children shown as colored
138
+ bars spanning the days they cover. An entry's title uses its first visible
139
+ day; every remaining visible day becomes one shared body for wrapped
140
+ details and an optional ending footer. Overlapping entries stack into
141
+ side-by-side lanes rather than being layered/hidden. Read-only.
142
+
143
+ Lanes are computed independently per instance, from only the entries
144
+ overlapping this month — an entry spanning a month boundary may therefore
145
+ land in a different lane index in the adjacent month's `calendar-month`.
146
+ This is an accepted v1 limitation: cross-month lane continuity would
147
+ require a shared parent (`calendar-year`) to assign lanes globally.
148
+
149
+ Entry attributes and slotted title/detail text are observed, so a
150
+ standalone month re-renders when consumers update declarative metadata.
151
+
152
+ Import: `import "@f-ewald/components/calendar-month.js";`
153
+
154
+ Properties: `year` (attribute `year`) : number, default —; `month` (attribute `month`) : number, default 1
155
+ Events: none
156
+ CSS custom properties: `--ui-border`, `--ui-danger`, `--ui-focus-ring`, `--ui-font`, `--ui-font-size`, `--ui-font-size-sm`, `--ui-font-size-xs`, `--ui-hover-overlay`, `--ui-primary`, `--ui-radius-sm`, `--ui-success`, `--ui-surface`, `--ui-surface-muted`, `--ui-text`, `--ui-text-muted`
157
+
158
+ Example:
159
+ ```html
160
+ <calendar-month year="2026" month="7">
161
+ <calendar-entry start="2026-07-10" end="2026-07-18" label="Vacation" color="success">
162
+ <span slot="title">Vacation</span>
163
+ <span slot="detail">Out of office</span>
164
+ <span slot="detail">Road trip along the California coast with several scenic stops</span>
165
+ <span slot="footer">Return July 19 at 6 PM</span>
166
+ </calendar-entry>
167
+ <calendar-entry start="2026-07-15" end="2026-07-20" label="Conference" color="warning" href="#conf">
168
+ <span slot="detail">Talks and workshops</span>
169
+ <span slot="footer">Closing keynote · July 20</span>
170
+ </calendar-entry>
171
+ </calendar-month>
172
+ ```
173
+
174
+ ## <calendar-year>
175
+
176
+ A full year of `calendar-month` blocks, generated from declarative
177
+ `calendar-entry` children. Each entry is re-projected into the
178
+ `calendar-month` blocks it overlaps as a freshly-created `calendar-entry`
179
+ element — the original elements stay slotted here and are never moved,
180
+ since a DOM node can only have one parent. Read-only.
181
+
182
+ Import: `import "@f-ewald/components/calendar-year.js";`
183
+
184
+ Properties: `year` (attribute `year`) : number, default —
185
+ Events: none
186
+ CSS custom properties: `--ui-font`
187
+
188
+ Example:
189
+ ```html
190
+ <calendar-year year="2026">
191
+ <calendar-entry start="2026-01-28" end="2026-02-03" label="Offsite" color="primary" href="#offsite">
192
+ <span slot="detail">New York</span>
193
+ <span slot="detail">Team workshops</span>
194
+ <span slot="footer">Closing dinner Friday</span>
195
+ </calendar-entry>
196
+ <calendar-entry start="2026-03-05" end="2026-03-18" label="Product launch" color="success" href="#launch">
197
+ <span slot="detail">Coordinate the release across engineering, design, support, and marketing.</span>
198
+ <span slot="detail">Monitor adoption and production health throughout the rollout.</span>
199
+ <span slot="footer">Public launch · March 18 at 9 AM</span>
200
+ </calendar-entry>
201
+ <calendar-entry start="2026-07-10" end="2026-07-18" label="Vacation" color="success"></calendar-entry>
202
+ </calendar-year>
203
+ ```
204
+
107
205
  ## <chat-message>
108
206
 
109
207
  One conversation entry in a chat-style activity feed. Tool calls and
@@ -306,21 +404,32 @@ pushes the chevron to the far edge), but the host itself stays
306
404
  bar, a status picker) keep shrink-to-fit auto-width unchanged. To make an
307
405
  instance full-width, size the host itself: `form-select { width: 100%; }`.
308
406
 
407
+ Set `searchable` to replace the button trigger with an editable combobox
408
+ that filters the predefined options by case-insensitive label infix. Typed
409
+ text is only a query: `value` changes exclusively when an actual option is
410
+ selected, and an uncommitted query is discarded when the list closes.
411
+ Each option may also provide a pre-rendered `icon` and square `iconSize`;
412
+ iconless options reserve no leading space.
413
+
309
414
  Import: `import "@f-ewald/components/form-select.js";`
310
415
 
311
- Properties: `options` (JS property only) : SelectOption[], default []; `value` (attribute `value`) : string, default ""; `label` (attribute `label`) : string, default ""; `disabled` (attribute `disabled`) : boolean, default false
416
+ Properties: `options` (JS property only) : SelectOption[], default []; `value` (attribute `value`) : string, default ""; `label` (attribute `label`) : string, default ""; `disabled` (attribute `disabled`) : boolean, default false; `searchable` (attribute `searchable`) : boolean, default false
312
417
  Events: `change`
313
418
  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`
314
419
 
315
420
  Example:
316
421
  ```html
317
- <form-select label="Task state"></form-select>
422
+ <form-select label="Task state" searchable></form-select>
318
423
  <script type="module">
424
+ import { iconArrowPath, iconCheckCircle, iconListBullet } from "@f-ewald/components/icons.js";
425
+
319
426
  const select = document.querySelector("form-select");
320
427
  select.options = [
428
+ { value: "backlog", label: "Backlog", icon: iconListBullet(14), iconSize: 14 },
321
429
  { value: "open", label: "Open" },
322
- { value: "in_progress", label: "In progress" },
323
- { value: "done", label: "Done" },
430
+ { value: "in_progress", label: "In progress", icon: iconArrowPath(16), iconSize: 16 },
431
+ { value: "review", label: "Needs review" },
432
+ { value: "done", label: "Done", icon: iconCheckCircle(16), iconSize: 16 },
324
433
  ];
325
434
  select.value = "open";
326
435
  select.addEventListener("change", (e) => console.log(e.detail.value));
@@ -438,6 +547,9 @@ outer ring, no point/tail (unlike `<map-pin>`) — for markers that don't
438
547
  need to visually "point" at their exact coordinate. Purely a visual
439
548
  primitive — it has no `mapbox-gl` (or any mapping library) dependency;
440
549
  the consumer positions it, e.g. via `new mapboxgl.Marker({ element: el })`.
550
+ It can also replace the former `<map-point>` dense-layer primitive: use
551
+ `size="14" ring-width="3"`, leave the slot empty, and rasterize one marker
552
+ per color for use as a map `icon-image`.
441
553
 
442
554
  Import: `import "@f-ewald/components/map-circle.js";`
443
555
 
@@ -448,6 +560,7 @@ CSS custom properties: `--ui-font`
448
560
  Example:
449
561
  ```html
450
562
  <map-circle color="#6b7280"></map-circle>
563
+ <map-circle color="#0099D8" size="14" ring-width="3"></map-circle>
451
564
  <map-circle color="#1a73e8" size="24" ring-width="5" highlighted>1</map-circle>
452
565
  ```
453
566
 
@@ -470,30 +583,6 @@ Example:
470
583
  <map-pin color="#22c55e" size="26" highlighted>🏠</map-pin>
471
584
  ```
472
585
 
473
- ## <map-point>
474
-
475
- A small plain-colored map marker for dense point layers (transit stops,
476
- amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
477
- white ring, no badge/content slot — every instance on a given layer shares
478
- the same look, so there's nothing to render per-feature (unlike
479
- `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
480
- Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
481
- dependency; typically rasterized once per color and used as a Mapbox
482
- `icon-image` on a `symbol` layer rather than mounted as individual DOM
483
- markers, so a whole layer's worth of points shares one icon image.
484
-
485
- Import: `import "@f-ewald/components/map-point.js";`
486
-
487
- Properties: `color` (attribute `color`) : string, default "#4f46e5"; `size` (attribute `size`) : number, default 14; `ringWidth` (attribute `ring-width`) : number, default 3
488
- Events: none
489
- CSS custom properties: none
490
-
491
- Example:
492
- ```html
493
- <map-point color="#0099D8"></map-point>
494
- <map-point color="#fb8072" size="10" ring-width="2"></map-point>
495
- ```
496
-
497
586
  ## <percent-bar-chart>
498
587
 
499
588
  Horizontal bar chart for labeled percentage rows, using D3's linear scale.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@f-ewald/components",
3
3
  "private": false,
4
- "version": "0.7.0",
4
+ "version": "1.0.0",
5
5
  "description": "A collection of universally usable web components for various tasks.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -30,17 +30,21 @@
30
30
  "docs"
31
31
  ],
32
32
  "sideEffects": [
33
- "./dist/**/*.js"
33
+ "./dist/**/*.js",
34
+ "./src/**/*.ts"
34
35
  ],
35
36
  "scripts": {
36
37
  "dev": "vite",
37
38
  "build": "rm -rf dist && tsc && node scripts/generate-tokens-css.mjs && chmod +x dist/mcp-server.js",
38
39
  "build:demo": "vite build",
40
+ "build:site": "node scripts/generate-docs.mjs --site && vite build --base=./ --outDir=pages-dist/playground",
41
+ "preview:site": "vite preview --outDir=pages-dist",
39
42
  "analyze": "cem analyze --litelement --globs \"src/**/*.ts\"",
40
43
  "docs": "npm run analyze && node scripts/generate-docs.mjs",
41
44
  "icons": "node scripts/generate-icons.mjs",
42
45
  "mcp": "node dist/mcp-server.js",
43
46
  "test": "playwright test",
47
+ "test:site": "playwright test --config playwright.site.config.ts",
44
48
  "prepublishOnly": "npm run build && npm run docs && npm run test"
45
49
  },
46
50
  "keywords": [
@@ -48,6 +52,10 @@
48
52
  ],
49
53
  "author": "Friedrich Ewald",
50
54
  "license": "BSD-3-Clause",
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/f-ewald/components.git"
58
+ },
51
59
  "dependencies": {
52
60
  "@modelcontextprotocol/sdk": "^1.29.0",
53
61
  "d3-array": "^3.2.4",
@@ -1,31 +0,0 @@
1
- import { LitElement } from "lit";
2
- /**
3
- * A small plain-colored map marker for dense point layers (transit stops,
4
- * amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
5
- * white ring, no badge/content slot — every instance on a given layer shares
6
- * the same look, so there's nothing to render per-feature (unlike
7
- * `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
8
- * Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
9
- * dependency; typically rasterized once per color and used as a Mapbox
10
- * `icon-image` on a `symbol` layer rather than mounted as individual DOM
11
- * markers, so a whole layer's worth of points shares one icon image.
12
- *
13
- * @element map-point
14
- */
15
- export declare class MapPoint extends LitElement {
16
- static styles: import("lit").CSSResult[];
17
- /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
18
- color: string;
19
- /** Diameter, in CSS pixels. */
20
- size: number;
21
- /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */
22
- ringWidth: number;
23
- private readonly _gradId;
24
- render(): import("lit-html").TemplateResult<1>;
25
- }
26
- declare global {
27
- interface HTMLElementTagNameMap {
28
- "map-point": MapPoint;
29
- }
30
- }
31
- //# sourceMappingURL=map-point.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"map-point.d.ts","sourceRoot":"","sources":["../src/map-point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAO5C;;;;;;;;;;;;GAYG;AACH,qBACa,QAAS,SAAQ,UAAU;IACtC,OAAgB,MAAM,4BAWpB;IAEF,4FAA4F;IAChF,KAAK,SAAa;IAC9B,+BAA+B;IACH,IAAI,SAAM;IACtC,wFAAwF;IACnC,SAAS,SAAK;IAEnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;IAE1D,MAAM,yCAoBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
package/dist/map-point.js DELETED
@@ -1,83 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- import { LitElement, css, html } from "lit";
8
- import { customElement, property } from "lit/decorators.js";
9
- import { tokens } from "./tokens.js";
10
- import { mixHex } from "./utils/color.js";
11
- let gradientIdCounter = 0;
12
- /**
13
- * A small plain-colored map marker for dense point layers (transit stops,
14
- * amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
15
- * white ring, no badge/content slot — every instance on a given layer shares
16
- * the same look, so there's nothing to render per-feature (unlike
17
- * `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
18
- * Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
19
- * dependency; typically rasterized once per color and used as a Mapbox
20
- * `icon-image` on a `symbol` layer rather than mounted as individual DOM
21
- * markers, so a whole layer's worth of points shares one icon image.
22
- *
23
- * @element map-point
24
- */
25
- let MapPoint = class MapPoint extends LitElement {
26
- constructor() {
27
- super(...arguments);
28
- /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */
29
- this.color = "#4f46e5";
30
- /** Diameter, in CSS pixels. */
31
- this.size = 14;
32
- /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */
33
- this.ringWidth = 3;
34
- this._gradId = `map-point-grad-${gradientIdCounter++}`;
35
- }
36
- static { this.styles = [
37
- tokens,
38
- css `
39
- :host {
40
- display: inline-block;
41
- line-height: 0;
42
- }
43
- svg {
44
- display: block;
45
- }
46
- `,
47
- ]; }
48
- render() {
49
- const light = mixHex(this.color, "#ffffff", 30);
50
- const dark = mixHex(this.color, "#000000", 30);
51
- return html `
52
- <svg
53
- width=${this.size}
54
- height=${this.size}
55
- viewBox="0 0 32 32"
56
- fill="none"
57
- xmlns="http://www.w3.org/2000/svg"
58
- >
59
- <defs>
60
- <linearGradient id=${this._gradId} x1="0" y1="0" x2="0" y2="1">
61
- <stop offset="0%" stop-color=${light} />
62
- <stop offset="100%" stop-color=${dark} />
63
- </linearGradient>
64
- </defs>
65
- <circle cx="16" cy="16" r="13" fill="url(#${this._gradId})" stroke="#ffffff" stroke-width=${this.ringWidth} />
66
- </svg>
67
- `;
68
- }
69
- };
70
- __decorate([
71
- property()
72
- ], MapPoint.prototype, "color", void 0);
73
- __decorate([
74
- property({ type: Number })
75
- ], MapPoint.prototype, "size", void 0);
76
- __decorate([
77
- property({ type: Number, attribute: "ring-width" })
78
- ], MapPoint.prototype, "ringWidth", void 0);
79
- MapPoint = __decorate([
80
- customElement("map-point")
81
- ], MapPoint);
82
- export { MapPoint };
83
- //# sourceMappingURL=map-point.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"map-point.js","sourceRoot":"","sources":["../src/map-point.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,IAAI,iBAAiB,GAAG,CAAC,CAAC;AAE1B;;;;;;;;;;;;GAYG;AAEI,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,UAAU;IAAjC;;QAcL,4FAA4F;QAChF,UAAK,GAAG,SAAS,CAAC;QAC9B,+BAA+B;QACH,SAAI,GAAG,EAAE,CAAC;QACtC,wFAAwF;QACnC,cAAS,GAAG,CAAC,CAAC;QAElD,YAAO,GAAG,kBAAkB,iBAAiB,EAAE,EAAE,CAAC;IAuBrE,CAAC;aA3CiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;KAQF;KACF,AAXqB,CAWpB;IAWO,MAAM;QACb,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAA;;gBAEC,IAAI,CAAC,IAAI;iBACR,IAAI,CAAC,IAAI;;;;;;+BAMK,IAAI,CAAC,OAAO;2CACA,KAAK;6CACH,IAAI;;;oDAGG,IAAI,CAAC,OAAO,oCAAoC,IAAI,CAAC,SAAS;;KAE7G,CAAC;IACJ,CAAC;CACF,CAAA;AA7Ba;IAAX,QAAQ,EAAE;uCAAmB;AAEF;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;sCAAW;AAEe;IAApD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;2CAAe;AAnBxD,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CA4CpB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { mixHex } from \"./utils/color.js\";\n\nlet gradientIdCounter = 0;\n\n/**\n * A small plain-colored map marker for dense point layers (transit stops,\n * amenities, hazard points, etc.): a light-to-dark gradient fill with a thin\n * white ring, no badge/content slot — every instance on a given layer shares\n * the same look, so there's nothing to render per-feature (unlike\n * `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).\n * Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)\n * dependency; typically rasterized once per color and used as a Mapbox\n * `icon-image` on a `symbol` layer rather than mounted as individual DOM\n * markers, so a whole layer's worth of points shares one icon image.\n *\n * @element map-point\n */\n@customElement(\"map-point\")\nexport class MapPoint extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-block;\n line-height: 0;\n }\n svg {\n display: block;\n }\n `,\n ];\n\n /** Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. */\n @property() color = \"#4f46e5\";\n /** Diameter, in CSS pixels. */\n @property({ type: Number }) size = 14;\n /** White outer ring thickness, in the same viewBox units as `size` (scales with it). */\n @property({ type: Number, attribute: \"ring-width\" }) ringWidth = 3;\n\n private readonly _gradId = `map-point-grad-${gradientIdCounter++}`;\n\n override render() {\n const light = mixHex(this.color, \"#ffffff\", 30);\n const dark = mixHex(this.color, \"#000000\", 30);\n return html`\n <svg\n width=${this.size}\n height=${this.size}\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=${this._gradId} x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=${light} />\n <stop offset=\"100%\" stop-color=${dark} />\n </linearGradient>\n </defs>\n <circle cx=\"16\" cy=\"16\" r=\"13\" fill=\"url(#${this._gradId})\" stroke=\"#ffffff\" stroke-width=${this.ringWidth} />\n </svg>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"map-point\": MapPoint;\n }\n}\n"]}
package/docs/map-point.md DELETED
@@ -1,44 +0,0 @@
1
- # `<map-point>`
2
-
3
- A small plain-colored map marker for dense point layers (transit stops,
4
- amenities, hazard points, etc.): a light-to-dark gradient fill with a thin
5
- white ring, no badge/content slot — every instance on a given layer shares
6
- the same look, so there's nothing to render per-feature (unlike
7
- `<map-pin>`/`<map-circle>`, which carry per-marker slotted content).
8
- Purely a visual primitive — it has no `mapbox-gl` (or any mapping library)
9
- dependency; typically rasterized once per color and used as a Mapbox
10
- `icon-image` on a `symbol` layer rather than mounted as individual DOM
11
- markers, so a whole layer's worth of points shares one icon image.
12
-
13
- ## Install
14
-
15
- ```js
16
- import "@f-ewald/components/map-point.js";
17
- ```
18
-
19
- ## Usage
20
-
21
- ```html
22
- <map-point color="#0099D8"></map-point>
23
- <map-point color="#fb8072" size="10" ring-width="2"></map-point>
24
- ```
25
-
26
- ## Attributes / properties
27
-
28
- | Property | Attribute | Type | Default | Description |
29
- | --- | --- | --- | --- | --- |
30
- | `color` | `color` | `string` | `"#4f46e5"` | Fill color; the gradient's light (top) and dark (bottom) stops are derived from this. |
31
- | `size` | `size` | `number` | `14` | Diameter, in CSS pixels. |
32
- | `ringWidth` | `ring-width` | `number` | `3` | White outer ring thickness, in the same viewBox units as `size` (scales with it). |
33
-
34
- ## Events
35
-
36
- _None._
37
-
38
- ## Slots
39
-
40
- _None._
41
-
42
- ## CSS custom properties
43
-
44
- _None._