@f-ewald/components 0.1.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 (102) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +147 -0
  3. package/custom-elements.json +3398 -0
  4. package/dist/address-autocomplete.d.ts +75 -0
  5. package/dist/address-autocomplete.d.ts.map +1 -0
  6. package/dist/address-autocomplete.js +342 -0
  7. package/dist/address-autocomplete.js.map +1 -0
  8. package/dist/animate-confetti.d.ts +53 -0
  9. package/dist/animate-confetti.d.ts.map +1 -0
  10. package/dist/animate-confetti.js +180 -0
  11. package/dist/animate-confetti.js.map +1 -0
  12. package/dist/autocomplete-input.d.ts +73 -0
  13. package/dist/autocomplete-input.d.ts.map +1 -0
  14. package/dist/autocomplete-input.js +309 -0
  15. package/dist/autocomplete-input.js.map +1 -0
  16. package/dist/confirm-dialog.d.ts +36 -0
  17. package/dist/confirm-dialog.d.ts.map +1 -0
  18. package/dist/confirm-dialog.js +191 -0
  19. package/dist/confirm-dialog.js.map +1 -0
  20. package/dist/copy-link-button.d.ts +27 -0
  21. package/dist/copy-link-button.d.ts.map +1 -0
  22. package/dist/copy-link-button.js +84 -0
  23. package/dist/copy-link-button.js.map +1 -0
  24. package/dist/distance-value.d.ts +24 -0
  25. package/dist/distance-value.d.ts.map +1 -0
  26. package/dist/distance-value.js +50 -0
  27. package/dist/distance-value.js.map +1 -0
  28. package/dist/distribution-chart.d.ts +52 -0
  29. package/dist/distribution-chart.d.ts.map +1 -0
  30. package/dist/distribution-chart.js +299 -0
  31. package/dist/distribution-chart.js.map +1 -0
  32. package/dist/icons.d.ts +32 -0
  33. package/dist/icons.d.ts.map +1 -0
  34. package/dist/icons.js +35 -0
  35. package/dist/icons.js.map +1 -0
  36. package/dist/index.d.ts +18 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +18 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/percent-bar-chart.d.ts +29 -0
  41. package/dist/percent-bar-chart.d.ts.map +1 -0
  42. package/dist/percent-bar-chart.js +92 -0
  43. package/dist/percent-bar-chart.js.map +1 -0
  44. package/dist/price-history-chart.d.ts +39 -0
  45. package/dist/price-history-chart.d.ts.map +1 -0
  46. package/dist/price-history-chart.js +217 -0
  47. package/dist/price-history-chart.js.map +1 -0
  48. package/dist/relative-time.d.ts +26 -0
  49. package/dist/relative-time.d.ts.map +1 -0
  50. package/dist/relative-time.js +64 -0
  51. package/dist/relative-time.js.map +1 -0
  52. package/dist/reveal-button.d.ts +19 -0
  53. package/dist/reveal-button.d.ts.map +1 -0
  54. package/dist/reveal-button.js +62 -0
  55. package/dist/reveal-button.js.map +1 -0
  56. package/dist/roman-numeral.d.ts +18 -0
  57. package/dist/roman-numeral.d.ts.map +1 -0
  58. package/dist/roman-numeral.js +54 -0
  59. package/dist/roman-numeral.js.map +1 -0
  60. package/dist/slide-panel.d.ts +27 -0
  61. package/dist/slide-panel.d.ts.map +1 -0
  62. package/dist/slide-panel.js +149 -0
  63. package/dist/slide-panel.js.map +1 -0
  64. package/dist/toast-notification.d.ts +53 -0
  65. package/dist/toast-notification.d.ts.map +1 -0
  66. package/dist/toast-notification.js +173 -0
  67. package/dist/toast-notification.js.map +1 -0
  68. package/dist/tokens.css +21 -0
  69. package/dist/tokens.d.ts +16 -0
  70. package/dist/tokens.d.ts.map +1 -0
  71. package/dist/tokens.js +79 -0
  72. package/dist/tokens.js.map +1 -0
  73. package/dist/utils/distance.d.ts +11 -0
  74. package/dist/utils/distance.d.ts.map +1 -0
  75. package/dist/utils/distance.js +25 -0
  76. package/dist/utils/distance.js.map +1 -0
  77. package/dist/utils/time.d.ts +10 -0
  78. package/dist/utils/time.d.ts.map +1 -0
  79. package/dist/utils/time.js +33 -0
  80. package/dist/utils/time.js.map +1 -0
  81. package/dist/weight-bar-chart.d.ts +29 -0
  82. package/dist/weight-bar-chart.d.ts.map +1 -0
  83. package/dist/weight-bar-chart.js +96 -0
  84. package/dist/weight-bar-chart.js.map +1 -0
  85. package/docs/address-autocomplete.md +68 -0
  86. package/docs/animate-confetti.md +34 -0
  87. package/docs/autocomplete-input.md +79 -0
  88. package/docs/confirm-dialog.md +65 -0
  89. package/docs/copy-link-button.md +46 -0
  90. package/docs/distance-value.md +38 -0
  91. package/docs/distribution-chart.md +51 -0
  92. package/docs/mcp-evaluation.md +31 -0
  93. package/docs/percent-bar-chart.md +40 -0
  94. package/docs/price-history-chart.md +44 -0
  95. package/docs/relative-time.md +37 -0
  96. package/docs/reveal-button.md +43 -0
  97. package/docs/roman-numeral.md +33 -0
  98. package/docs/slide-panel.md +56 -0
  99. package/docs/toast-notification.md +52 -0
  100. package/docs/weight-bar-chart.md +53 -0
  101. package/llms.txt +361 -0
  102. package/package.json +69 -0
@@ -0,0 +1,191 @@
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, nothing } from "lit";
8
+ import { customElement, property } from "lit/decorators.js";
9
+ import { iconArrowPath } from "./icons.js";
10
+ import { tokens } from "./tokens.js";
11
+ /**
12
+ * Reusable confirmation dialog: overlay + centered card with a slotted body,
13
+ * an optional error line, and Cancel/Confirm actions. Instant `display:none`
14
+ * → `display:flex` toggle (no transitions). Fires `confirm`/`cancel`
15
+ * (bubbling, composed) instead of owning any deletion logic itself —
16
+ * callers stay in charge of the request.
17
+ *
18
+ * @element confirm-dialog
19
+ * @fires confirm - User clicked the confirm button.
20
+ * @fires cancel - User clicked the cancel button.
21
+ */
22
+ let ConfirmDialog = class ConfirmDialog extends LitElement {
23
+ constructor() {
24
+ super(...arguments);
25
+ /** Whether the dialog is visible. */
26
+ this.open = false;
27
+ /** Label for the confirm button. */
28
+ this.confirmLabel = "Delete";
29
+ /** Label for the cancel button. */
30
+ this.cancelLabel = "Cancel";
31
+ /** Danger (red) vs. primary (indigo) styling for the confirm button. */
32
+ this.danger = true;
33
+ /** Shows a spinner and disables both buttons while a request is in flight. */
34
+ this.busy = false;
35
+ /** Inline error line shown below the body, or null for none. */
36
+ this.error = null;
37
+ }
38
+ static { this.styles = [
39
+ tokens,
40
+ css `
41
+ .overlay {
42
+ position: fixed;
43
+ inset: 0;
44
+ background: var(--ui-overlay, rgb(15 23 42 / 0.45));
45
+ z-index: 50;
46
+ display: none;
47
+ align-items: flex-start;
48
+ justify-content: center;
49
+ padding: 10vh 20px 20px;
50
+ box-sizing: border-box;
51
+ }
52
+ .overlay.open {
53
+ display: flex;
54
+ }
55
+ .dialog {
56
+ background: var(--ui-surface, #fff);
57
+ border-radius: var(--ui-radius, 0.5rem);
58
+ box-shadow: var(
59
+ --ui-shadow-lg,
60
+ 0 20px 25px -5px rgb(0 0 0 / 0.1),
61
+ 0 8px 10px -6px rgb(0 0 0 / 0.1)
62
+ );
63
+ width: 100%;
64
+ max-width: 420px;
65
+ padding: 1.25rem;
66
+ box-sizing: border-box;
67
+ }
68
+ .dialog-text {
69
+ margin: 0 0 1rem;
70
+ color: var(--ui-text, #0f172a);
71
+ font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);
72
+ font-size: var(--ui-font-size, 0.875rem);
73
+ line-height: 1.45;
74
+ }
75
+ .dialog-actions {
76
+ display: flex;
77
+ justify-content: flex-end;
78
+ gap: 0.6rem;
79
+ }
80
+ .btn-cancel {
81
+ background: none;
82
+ border: 1px solid var(--ui-border, #e2e8f0);
83
+ color: var(--ui-text, #0f172a);
84
+ border-radius: var(--ui-radius-sm, 0.25rem);
85
+ padding: 0.5rem 0.9rem;
86
+ font-size: var(--ui-font-size-sm, 0.75rem);
87
+ cursor: pointer;
88
+ font-family: inherit;
89
+ }
90
+ .btn-cancel:hover:not(:disabled) {
91
+ border-color: var(--ui-text-muted, #64748b);
92
+ }
93
+ .btn-danger,
94
+ .btn-primary {
95
+ border: none;
96
+ border-radius: var(--ui-radius-sm, 0.25rem);
97
+ padding: 0.5rem 0.9rem;
98
+ font-size: var(--ui-font-size-sm, 0.75rem);
99
+ font-weight: 500;
100
+ cursor: pointer;
101
+ display: inline-flex;
102
+ align-items: center;
103
+ gap: 0.35rem;
104
+ font-family: inherit;
105
+ }
106
+ .btn-danger {
107
+ background: var(--ui-danger, #dc2626);
108
+ color: #fff;
109
+ }
110
+ .btn-danger:hover:not(:disabled) {
111
+ background: var(--ui-danger-hover, #b91c1c);
112
+ }
113
+ .btn-primary {
114
+ background: var(--ui-primary, #4f46e5);
115
+ color: #fff;
116
+ }
117
+ .btn-primary:hover:not(:disabled) {
118
+ background: var(--ui-primary-hover, #4338ca);
119
+ }
120
+ button:disabled {
121
+ opacity: 0.6;
122
+ cursor: default;
123
+ }
124
+ .error-text {
125
+ color: var(--ui-danger, #dc2626);
126
+ font-size: var(--ui-font-size-sm, 0.75rem);
127
+ margin: 0.4rem 0 0.8rem;
128
+ }
129
+ .spin {
130
+ display: inline-flex;
131
+ animation: spin 0.8s linear infinite;
132
+ }
133
+ @keyframes spin {
134
+ to {
135
+ transform: rotate(360deg);
136
+ }
137
+ }
138
+ @media (max-width: 768px) {
139
+ .overlay {
140
+ padding: 12px;
141
+ overflow-y: auto;
142
+ }
143
+ }
144
+ `,
145
+ ]; }
146
+ _confirm() {
147
+ this.dispatchEvent(new CustomEvent("confirm", { bubbles: true, composed: true }));
148
+ }
149
+ _cancel() {
150
+ this.dispatchEvent(new CustomEvent("cancel", { bubbles: true, composed: true }));
151
+ }
152
+ render() {
153
+ return html `
154
+ <div class="overlay ${this.open ? "open" : ""}">
155
+ <div class="dialog">
156
+ <p class="dialog-text"><slot></slot></p>
157
+ ${this.error ? html `<p class="error-text">${this.error}</p>` : nothing}
158
+ <div class="dialog-actions">
159
+ <button class="btn-cancel" ?disabled=${this.busy} @click=${this._cancel}>${this.cancelLabel}</button>
160
+ <button class=${this.danger ? "btn-danger" : "btn-primary"} ?disabled=${this.busy} @click=${this._confirm}>
161
+ ${this.busy ? html `<span class="spin">${iconArrowPath(14)}</span>` : nothing} ${this.confirmLabel}
162
+ </button>
163
+ </div>
164
+ </div>
165
+ </div>
166
+ `;
167
+ }
168
+ };
169
+ __decorate([
170
+ property({ type: Boolean })
171
+ ], ConfirmDialog.prototype, "open", void 0);
172
+ __decorate([
173
+ property({ attribute: "confirm-label" })
174
+ ], ConfirmDialog.prototype, "confirmLabel", void 0);
175
+ __decorate([
176
+ property({ attribute: "cancel-label" })
177
+ ], ConfirmDialog.prototype, "cancelLabel", void 0);
178
+ __decorate([
179
+ property({ type: Boolean })
180
+ ], ConfirmDialog.prototype, "danger", void 0);
181
+ __decorate([
182
+ property({ type: Boolean })
183
+ ], ConfirmDialog.prototype, "busy", void 0);
184
+ __decorate([
185
+ property()
186
+ ], ConfirmDialog.prototype, "error", void 0);
187
+ ConfirmDialog = __decorate([
188
+ customElement("confirm-dialog")
189
+ ], ConfirmDialog);
190
+ export { ConfirmDialog };
191
+ //# sourceMappingURL=confirm-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-dialog.js","sourceRoot":"","sources":["../src/confirm-dialog.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;GAUG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;QA8GL,qCAAqC;QACR,SAAI,GAAG,KAAK,CAAC;QAC1C,oCAAoC;QACM,iBAAY,GAAG,QAAQ,CAAC;QAClE,mCAAmC;QACM,gBAAW,GAAG,QAAQ,CAAC;QAChE,wEAAwE;QAC3C,WAAM,GAAG,IAAI,CAAC;QAC3C,8EAA8E;QACjD,SAAI,GAAG,KAAK,CAAC;QAC1C,gEAAgE;QACpD,UAAK,GAAkB,IAAI,CAAC;IA0B1C,CAAC;aAlJiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAwGF;KACF,AA3GqB,CA2GpB;IAeM,QAAQ;QACd,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACpF,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACnF,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;4BACa,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;;;YAGvC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,yBAAyB,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO;;mDAE7B,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW;4BAC3E,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,cAAc,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,QAAQ;gBACrG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,sBAAsB,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,YAAY;;;;;KAK1G,CAAC;IACJ,CAAC;CACF,CAAA;AApC8B;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;2CAAc;AAEA;IAAzC,QAAQ,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;mDAAyB;AAEzB;IAAxC,QAAQ,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;kDAAwB;AAEnC;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;6CAAe;AAEd;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;2CAAc;AAE9B;IAAX,QAAQ,EAAE;4CAA6B;AAzH7B,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CAmJzB","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { iconArrowPath } from \"./icons.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * Reusable confirmation dialog: overlay + centered card with a slotted body,\n * an optional error line, and Cancel/Confirm actions. Instant `display:none`\n * → `display:flex` toggle (no transitions). Fires `confirm`/`cancel`\n * (bubbling, composed) instead of owning any deletion logic itself —\n * callers stay in charge of the request.\n *\n * @element confirm-dialog\n * @fires confirm - User clicked the confirm button.\n * @fires cancel - User clicked the cancel button.\n */\n@customElement(\"confirm-dialog\")\nexport class ConfirmDialog extends LitElement {\n static override styles = [\n tokens,\n css`\n .overlay {\n position: fixed;\n inset: 0;\n background: var(--ui-overlay, rgb(15 23 42 / 0.45));\n z-index: 50;\n display: none;\n align-items: flex-start;\n justify-content: center;\n padding: 10vh 20px 20px;\n box-sizing: border-box;\n }\n .overlay.open {\n display: flex;\n }\n .dialog {\n background: var(--ui-surface, #fff);\n border-radius: var(--ui-radius, 0.5rem);\n box-shadow: var(\n --ui-shadow-lg,\n 0 20px 25px -5px rgb(0 0 0 / 0.1),\n 0 8px 10px -6px rgb(0 0 0 / 0.1)\n );\n width: 100%;\n max-width: 420px;\n padding: 1.25rem;\n box-sizing: border-box;\n }\n .dialog-text {\n margin: 0 0 1rem;\n color: var(--ui-text, #0f172a);\n font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);\n font-size: var(--ui-font-size, 0.875rem);\n line-height: 1.45;\n }\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: 0.6rem;\n }\n .btn-cancel {\n background: none;\n border: 1px solid var(--ui-border, #e2e8f0);\n color: var(--ui-text, #0f172a);\n border-radius: var(--ui-radius-sm, 0.25rem);\n padding: 0.5rem 0.9rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n cursor: pointer;\n font-family: inherit;\n }\n .btn-cancel:hover:not(:disabled) {\n border-color: var(--ui-text-muted, #64748b);\n }\n .btn-danger,\n .btn-primary {\n border: none;\n border-radius: var(--ui-radius-sm, 0.25rem);\n padding: 0.5rem 0.9rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: 500;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 0.35rem;\n font-family: inherit;\n }\n .btn-danger {\n background: var(--ui-danger, #dc2626);\n color: #fff;\n }\n .btn-danger:hover:not(:disabled) {\n background: var(--ui-danger-hover, #b91c1c);\n }\n .btn-primary {\n background: var(--ui-primary, #4f46e5);\n color: #fff;\n }\n .btn-primary:hover:not(:disabled) {\n background: var(--ui-primary-hover, #4338ca);\n }\n button:disabled {\n opacity: 0.6;\n cursor: default;\n }\n .error-text {\n color: var(--ui-danger, #dc2626);\n font-size: var(--ui-font-size-sm, 0.75rem);\n margin: 0.4rem 0 0.8rem;\n }\n .spin {\n display: inline-flex;\n animation: spin 0.8s linear infinite;\n }\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n @media (max-width: 768px) {\n .overlay {\n padding: 12px;\n overflow-y: auto;\n }\n }\n `,\n ];\n\n /** Whether the dialog is visible. */\n @property({ type: Boolean }) open = false;\n /** Label for the confirm button. */\n @property({ attribute: \"confirm-label\" }) confirmLabel = \"Delete\";\n /** Label for the cancel button. */\n @property({ attribute: \"cancel-label\" }) cancelLabel = \"Cancel\";\n /** Danger (red) vs. primary (indigo) styling for the confirm button. */\n @property({ type: Boolean }) danger = true;\n /** Shows a spinner and disables both buttons while a request is in flight. */\n @property({ type: Boolean }) busy = false;\n /** Inline error line shown below the body, or null for none. */\n @property() error: string | null = null;\n\n private _confirm() {\n this.dispatchEvent(new CustomEvent(\"confirm\", { bubbles: true, composed: true }));\n }\n\n private _cancel() {\n this.dispatchEvent(new CustomEvent(\"cancel\", { bubbles: true, composed: true }));\n }\n\n override render() {\n return html`\n <div class=\"overlay ${this.open ? \"open\" : \"\"}\">\n <div class=\"dialog\">\n <p class=\"dialog-text\"><slot></slot></p>\n ${this.error ? html`<p class=\"error-text\">${this.error}</p>` : nothing}\n <div class=\"dialog-actions\">\n <button class=\"btn-cancel\" ?disabled=${this.busy} @click=${this._cancel}>${this.cancelLabel}</button>\n <button class=${this.danger ? \"btn-danger\" : \"btn-primary\"} ?disabled=${this.busy} @click=${this._confirm}>\n ${this.busy ? html`<span class=\"spin\">${iconArrowPath(14)}</span>` : nothing} ${this.confirmLabel}\n </button>\n </div>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"confirm-dialog\": ConfirmDialog;\n }\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * Small icon button that copies `value` to the clipboard and shows a toast
4
+ * on success/failure (if a `<toast-notification>` element is present), and
5
+ * always dispatches a `copy-success`/`copy-error` CustomEvent so consumers
6
+ * without a toast element can react. Defaults to the current page URL if
7
+ * `value` is unset.
8
+ *
9
+ * @element copy-link-button
10
+ * @fires copy-success - The value was copied to the clipboard.
11
+ * @fires copy-error - Copying to the clipboard failed.
12
+ */
13
+ export declare class CopyLinkButton extends LitElement {
14
+ /** Text to copy. Defaults to `window.location.href` at click time. */
15
+ value: string;
16
+ /** Accessible label / tooltip text. */
17
+ label: string;
18
+ static styles: import("lit").CSSResult[];
19
+ private _onClick;
20
+ render(): import("lit-html").TemplateResult<1>;
21
+ }
22
+ declare global {
23
+ interface HTMLElementTagNameMap {
24
+ "copy-link-button": CopyLinkButton;
25
+ }
26
+ }
27
+ //# sourceMappingURL=copy-link-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-link-button.d.ts","sourceRoot":"","sources":["../src/copy-link-button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAM5C;;;;;;;;;;GAUG;AACH,qBACa,cAAe,SAAQ,UAAU;IAC5C,sEAAsE;IAC1D,KAAK,SAAM;IACvB,uCAAuC;IAC3B,KAAK,SAAe;IAEhC,OAAgB,MAAM,4BAsBpB;YAEY,QAAQ;IAYb,MAAM,yCAMd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,cAAc,CAAC;KACpC;CACF"}
@@ -0,0 +1,84 @@
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 { iconLink } from "./icons.js";
10
+ import { notifyError, notifySuccess } from "./toast-notification.js";
11
+ import { tokens } from "./tokens.js";
12
+ /**
13
+ * Small icon button that copies `value` to the clipboard and shows a toast
14
+ * on success/failure (if a `<toast-notification>` element is present), and
15
+ * always dispatches a `copy-success`/`copy-error` CustomEvent so consumers
16
+ * without a toast element can react. Defaults to the current page URL if
17
+ * `value` is unset.
18
+ *
19
+ * @element copy-link-button
20
+ * @fires copy-success - The value was copied to the clipboard.
21
+ * @fires copy-error - Copying to the clipboard failed.
22
+ */
23
+ let CopyLinkButton = class CopyLinkButton extends LitElement {
24
+ constructor() {
25
+ super(...arguments);
26
+ /** Text to copy. Defaults to `window.location.href` at click time. */
27
+ this.value = "";
28
+ /** Accessible label / tooltip text. */
29
+ this.label = "Copy link";
30
+ }
31
+ static { this.styles = [
32
+ tokens,
33
+ css `
34
+ :host {
35
+ display: inline-flex;
36
+ }
37
+ button {
38
+ background: none;
39
+ border: none;
40
+ cursor: pointer;
41
+ padding: 4px;
42
+ color: var(--ui-text-muted, #64748b);
43
+ border-radius: var(--ui-radius-sm, 0.25rem);
44
+ display: inline-flex;
45
+ align-items: center;
46
+ justify-content: center;
47
+ }
48
+ button:hover {
49
+ background: var(--ui-surface-muted, #f8fafc);
50
+ color: var(--ui-text, #0f172a);
51
+ }
52
+ `,
53
+ ]; }
54
+ async _onClick() {
55
+ const text = this.value || window.location.href;
56
+ try {
57
+ await navigator.clipboard.writeText(text);
58
+ notifySuccess("Link copied to clipboard");
59
+ this.dispatchEvent(new CustomEvent("copy-success", { bubbles: true, composed: true }));
60
+ }
61
+ catch {
62
+ notifyError("Couldn't copy the link");
63
+ this.dispatchEvent(new CustomEvent("copy-error", { bubbles: true, composed: true }));
64
+ }
65
+ }
66
+ render() {
67
+ return html `
68
+ <button type="button" aria-label=${this.label} title=${this.label} @click=${this._onClick}>
69
+ ${iconLink(16)}
70
+ </button>
71
+ `;
72
+ }
73
+ };
74
+ __decorate([
75
+ property()
76
+ ], CopyLinkButton.prototype, "value", void 0);
77
+ __decorate([
78
+ property()
79
+ ], CopyLinkButton.prototype, "label", void 0);
80
+ CopyLinkButton = __decorate([
81
+ customElement("copy-link-button")
82
+ ], CopyLinkButton);
83
+ export { CopyLinkButton };
84
+ //# sourceMappingURL=copy-link-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-link-button.js","sourceRoot":"","sources":["../src/copy-link-button.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,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;GAUG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAAvC;;QACL,sEAAsE;QAC1D,UAAK,GAAG,EAAE,CAAC;QACvB,uCAAuC;QAC3B,UAAK,GAAG,WAAW,CAAC;IA6ClC,CAAC;aA3CiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;KAmBF;KACF,AAtBqB,CAsBpB;IAEM,KAAK,CAAC,QAAQ;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC1C,aAAa,CAAC,0BAA0B,CAAC,CAAC;YAC1C,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzF,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,wBAAwB,CAAC,CAAC;YACtC,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;yCAC0B,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,QAAQ;UACrF,QAAQ,CAAC,EAAE,CAAC;;KAEjB,CAAC;IACJ,CAAC;CACF,CAAA;AA/Ca;IAAX,QAAQ,EAAE;6CAAY;AAEX;IAAX,QAAQ,EAAE;6CAAqB;AAJrB,cAAc;IAD1B,aAAa,CAAC,kBAAkB,CAAC;GACrB,cAAc,CAiD1B","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { iconLink } from \"./icons.js\";\nimport { notifyError, notifySuccess } from \"./toast-notification.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * Small icon button that copies `value` to the clipboard and shows a toast\n * on success/failure (if a `<toast-notification>` element is present), and\n * always dispatches a `copy-success`/`copy-error` CustomEvent so consumers\n * without a toast element can react. Defaults to the current page URL if\n * `value` is unset.\n *\n * @element copy-link-button\n * @fires copy-success - The value was copied to the clipboard.\n * @fires copy-error - Copying to the clipboard failed.\n */\n@customElement(\"copy-link-button\")\nexport class CopyLinkButton extends LitElement {\n /** Text to copy. Defaults to `window.location.href` at click time. */\n @property() value = \"\";\n /** Accessible label / tooltip text. */\n @property() label = \"Copy link\";\n\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-flex;\n }\n button {\n background: none;\n border: none;\n cursor: pointer;\n padding: 4px;\n color: var(--ui-text-muted, #64748b);\n border-radius: var(--ui-radius-sm, 0.25rem);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n }\n button:hover {\n background: var(--ui-surface-muted, #f8fafc);\n color: var(--ui-text, #0f172a);\n }\n `,\n ];\n\n private async _onClick() {\n const text = this.value || window.location.href;\n try {\n await navigator.clipboard.writeText(text);\n notifySuccess(\"Link copied to clipboard\");\n this.dispatchEvent(new CustomEvent(\"copy-success\", { bubbles: true, composed: true }));\n } catch {\n notifyError(\"Couldn't copy the link\");\n this.dispatchEvent(new CustomEvent(\"copy-error\", { bubbles: true, composed: true }));\n }\n }\n\n override render() {\n return html`\n <button type=\"button\" aria-label=${this.label} title=${this.label} @click=${this._onClick}>\n ${iconLink(16)}\n </button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"copy-link-button\": CopyLinkButton;\n }\n}\n"]}
@@ -0,0 +1,24 @@
1
+ import { LitElement, nothing } from "lit";
2
+ /**
3
+ * Inline distance display. Renders miles/feet or km/m, switching units at
4
+ * sensible thresholds (< 0.25 mi → ft; < 0.5 km → m).
5
+ *
6
+ * Supply exactly one of `miles` or `km`; the other stays null.
7
+ * km support is present but reserved for future use.
8
+ *
9
+ * @element distance-value
10
+ */
11
+ export declare class DistanceValue extends LitElement {
12
+ static styles: import("lit").CSSResult;
13
+ /** Distance in miles (imperial). Switches to feet below 0.25 mi. */
14
+ miles: number | null;
15
+ /** Distance in kilometers (metric, future). Switches to meters below 0.5 km. */
16
+ km: number | null;
17
+ render(): typeof nothing | import("lit-html").TemplateResult<1>;
18
+ }
19
+ declare global {
20
+ interface HTMLElementTagNameMap {
21
+ "distance-value": DistanceValue;
22
+ }
23
+ }
24
+ //# sourceMappingURL=distance-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distance-value.d.ts","sourceRoot":"","sources":["../src/distance-value.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,OAAO,EAAE,MAAM,KAAK,CAAC;AAIrD;;;;;;;;GAQG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,OAAgB,MAAM,0BAIpB;IAEF,oEAAoE;IACxC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExD,gFAAgF;IACpD,EAAE,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5C,MAAM,0DAId;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
@@ -0,0 +1,50 @@
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, nothing } from "lit";
8
+ import { customElement, property } from "lit/decorators.js";
9
+ import { formatMiles, formatKm } from "./utils/distance.js";
10
+ /**
11
+ * Inline distance display. Renders miles/feet or km/m, switching units at
12
+ * sensible thresholds (< 0.25 mi → ft; < 0.5 km → m).
13
+ *
14
+ * Supply exactly one of `miles` or `km`; the other stays null.
15
+ * km support is present but reserved for future use.
16
+ *
17
+ * @element distance-value
18
+ */
19
+ let DistanceValue = class DistanceValue extends LitElement {
20
+ constructor() {
21
+ super(...arguments);
22
+ /** Distance in miles (imperial). Switches to feet below 0.25 mi. */
23
+ this.miles = null;
24
+ /** Distance in kilometers (metric, future). Switches to meters below 0.5 km. */
25
+ this.km = null;
26
+ }
27
+ static { this.styles = css `
28
+ :host {
29
+ display: inline;
30
+ }
31
+ `; }
32
+ render() {
33
+ if (this.km != null)
34
+ return html `${formatKm(this.km)}`;
35
+ if (this.miles != null)
36
+ return html `${formatMiles(this.miles)}`;
37
+ return nothing;
38
+ }
39
+ };
40
+ __decorate([
41
+ property({ type: Number })
42
+ ], DistanceValue.prototype, "miles", void 0);
43
+ __decorate([
44
+ property({ type: Number })
45
+ ], DistanceValue.prototype, "km", void 0);
46
+ DistanceValue = __decorate([
47
+ customElement("distance-value")
48
+ ], DistanceValue);
49
+ export { DistanceValue };
50
+ //# sourceMappingURL=distance-value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distance-value.js","sourceRoot":"","sources":["../src/distance-value.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;;;GAQG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,UAAU;IAAtC;;QAOL,oEAAoE;QACxC,UAAK,GAAkB,IAAI,CAAC;QAExD,gFAAgF;QACpD,OAAE,GAAkB,IAAI,CAAC;IAOvD,CAAC;aAjBiB,WAAM,GAAG,GAAG,CAAA;;;;GAI3B,AAJqB,CAIpB;IAQO,MAAM;QACb,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI;YAAE,OAAO,IAAI,CAAA,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACvD,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI;YAAE,OAAO,IAAI,CAAA,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAA;AAV6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;4CAA6B;AAG5B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;yCAA0B;AAX1C,aAAa;IADzB,aAAa,CAAC,gBAAgB,CAAC;GACnB,aAAa,CAkBzB","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { formatMiles, formatKm } from \"./utils/distance.js\";\n\n/**\n * Inline distance display. Renders miles/feet or km/m, switching units at\n * sensible thresholds (< 0.25 mi → ft; < 0.5 km → m).\n *\n * Supply exactly one of `miles` or `km`; the other stays null.\n * km support is present but reserved for future use.\n *\n * @element distance-value\n */\n@customElement(\"distance-value\")\nexport class DistanceValue extends LitElement {\n static override styles = css`\n :host {\n display: inline;\n }\n `;\n\n /** Distance in miles (imperial). Switches to feet below 0.25 mi. */\n @property({ type: Number }) miles: number | null = null;\n\n /** Distance in kilometers (metric, future). Switches to meters below 0.5 km. */\n @property({ type: Number }) km: number | null = null;\n\n override render() {\n if (this.km != null) return html`${formatKm(this.km)}`;\n if (this.miles != null) return html`${formatMiles(this.miles)}`;\n return nothing;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"distance-value\": DistanceValue;\n }\n}\n"]}
@@ -0,0 +1,52 @@
1
+ import { LitElement, nothing } from "lit";
2
+ export interface DistributionValue {
3
+ /** Short label shown on the chart marker, e.g. 'A'. Empty string = show raw value instead. */
4
+ label: string;
5
+ value: number;
6
+ }
7
+ /**
8
+ * Renders a KDE distribution curve for a named metric with one or more value
9
+ * markers. The SVG viewBox is kept in sync with the element's pixel width via
10
+ * ResizeObserver so that font sizes and stroke widths are always in real pixels
11
+ * regardless of container width.
12
+ *
13
+ * Pass `fontSize` to control all text size (default 11). Pass a single
14
+ * `{label:'', value}` for a single-value display or multiple
15
+ * `{label:'A'|'B'|...}` entries to compare several values.
16
+ *
17
+ * @element distribution-chart
18
+ */
19
+ export declare class DistributionChart extends LitElement {
20
+ static styles: import("lit").CSSResult[];
21
+ /** Metric name, fetched from `/api/distribution/<metric>` on change. */
22
+ metric: string;
23
+ /** One or more values to mark on the distribution curve. */
24
+ values: DistributionValue[];
25
+ /** Colors assigned to markers in order. Defaults to indigo/amber/teal/rose 600s. */
26
+ markerColors: string[];
27
+ /** Target font size in CSS pixels (default 11). Always renders at this size regardless of container width. */
28
+ fontSize: number;
29
+ private _data;
30
+ private _loading;
31
+ private _error;
32
+ /** Measured element width in CSS pixels. 0 until ResizeObserver fires. */
33
+ private _width;
34
+ /** Inner x coordinate (px) of the current hover position, or null when not hovering. */
35
+ private _hoverX;
36
+ private _fetchedFor;
37
+ private _ro;
38
+ connectedCallback(): void;
39
+ firstUpdated(): void;
40
+ disconnectedCallback(): void;
41
+ updated(changed: Map<string, unknown>): void;
42
+ private _maybeFetch;
43
+ private _renderSvg;
44
+ private _renderLegend;
45
+ render(): typeof nothing | import("lit-html").TemplateResult<1>;
46
+ }
47
+ declare global {
48
+ interface HTMLElementTagNameMap {
49
+ "distribution-chart": DistributionChart;
50
+ }
51
+ }
52
+ //# sourceMappingURL=distribution-chart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"distribution-chart.d.ts","sourceRoot":"","sources":["../src/distribution-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,OAAO,EAAO,MAAM,KAAK,CAAC;AAqB1D,MAAM,WAAW,iBAAiB;IAChC,8FAA8F;IAC9F,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AASD;;;;;;;;;;;GAWG;AACH,qBACa,iBAAkB,SAAQ,UAAU;IAC/C,OAAgB,MAAM,4BAgEpB;IAEF,wEAAwE;IAC5D,MAAM,SAAM;IACxB,4DAA4D;IAC5B,MAAM,EAAE,iBAAiB,EAAE,CAAM;IACjE,oFAAoF;IACpD,YAAY,EAAE,MAAM,EAAE,CAAyB;IAC/E,8GAA8G;IAC1D,QAAQ,SAAM;IAEzD,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAuB;IAC9C,0EAA0E;IACjE,OAAO,CAAC,MAAM,CAAK;IAC5B,wFAAwF;IAC/E,OAAO,CAAC,OAAO,CAAuB;IAE/C,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,GAAG,CAA+B;IAEjC,iBAAiB,SAGzB;IAEQ,YAAY,SAMpB;IAEQ,oBAAoB,SAI5B;IAEQ,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,QAE7C;IAED,OAAO,CAAC,WAAW;IAoBnB,OAAO,CAAC,UAAU;IAuFlB,OAAO,CAAC,aAAa;IAmBZ,MAAM,0DAUd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,iBAAiB,CAAC;KACzC;CACF"}