@f-ewald/components 1.8.0 → 1.10.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.
@@ -0,0 +1,44 @@
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 } from "lit/decorators.js";
9
+ import { tokens } from "./tokens.js";
10
+ /**
11
+ * A responsive auto-filling grid shell for `link-card` (or any card-shaped
12
+ * content) — each slotted child becomes a grid item, wrapping to a new row
13
+ * once the container is too narrow for another `15rem` column.
14
+ *
15
+ * @element card-grid
16
+ * @slot - `link-card` elements (or other card-shaped content).
17
+ */
18
+ let CardGrid = class CardGrid extends LitElement {
19
+ static { this.styles = [
20
+ tokens,
21
+ css `
22
+ :host {
23
+ display: block;
24
+ }
25
+ .grid {
26
+ display: grid;
27
+ grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
28
+ gap: 1rem;
29
+ }
30
+ `,
31
+ ]; }
32
+ render() {
33
+ return html `
34
+ <div class="grid">
35
+ <slot></slot>
36
+ </div>
37
+ `;
38
+ }
39
+ };
40
+ CardGrid = __decorate([
41
+ customElement("card-grid")
42
+ ], CardGrid);
43
+ export { CardGrid };
44
+ //# sourceMappingURL=card-grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-grid.js","sourceRoot":"","sources":["../src/card-grid.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;GAOG;AAEI,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,UAAU;aACtB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;KASF;KACF,AAZqB,CAYpB;IAEO,MAAM;QACb,OAAO,IAAI,CAAA;;;;KAIV,CAAC;IACJ,CAAC;CACF,CAAA;AAtBY,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CAsBpB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * A responsive auto-filling grid shell for `link-card` (or any card-shaped\n * content) — each slotted child becomes a grid item, wrapping to a new row\n * once the container is too narrow for another `15rem` column.\n *\n * @element card-grid\n * @slot - `link-card` elements (or other card-shaped content).\n */\n@customElement(\"card-grid\")\nexport class CardGrid extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n }\n .grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));\n gap: 1rem;\n }\n `,\n ];\n\n override render() {\n return html`\n <div class=\"grid\">\n <slot></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"card-grid\": CardGrid;\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ export { MapPin } from "./map-pin.js";
22
22
  export { MapCircle } from "./map-circle.js";
23
23
  export { RadioCards, type RadioCardOption } from "./radio-cards.js";
24
24
  export { RadioPills, type RadioPillOption } from "./radio-pills.js";
25
+ export { ButtonGroup, type ButtonGroupOption } from "./button-group.js";
25
26
  export { UiButton, type ButtonVariant } from "./ui-button.js";
26
27
  export { StatMeter } from "./stat-meter.js";
27
28
  export { StatusPill, type StatusPillColor } from "./status-pill.js";
@@ -52,6 +53,8 @@ export { KanbanBoard, type KanbanCardData, type KanbanColumnData, type KanbanCar
52
53
  export { KanbanColumn } from "./kanban-column.js";
53
54
  export { KanbanCard } from "./kanban-card.js";
54
55
  export { TextArea } from "./text-area.js";
56
+ export { LinkCard, type LinkCardStatus } from "./link-card.js";
57
+ export { CardGrid } from "./card-grid.js";
55
58
  export { formatDuration, type DurationFormat } from "./utils/duration.js";
56
59
  export { tokens, tokenValues, darkTokenValues } from "./tokens.js";
57
60
  export * from "./icons.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ export { MapPin } from "./map-pin.js";
22
22
  export { MapCircle } from "./map-circle.js";
23
23
  export { RadioCards } from "./radio-cards.js";
24
24
  export { RadioPills } from "./radio-pills.js";
25
+ export { ButtonGroup } from "./button-group.js";
25
26
  export { UiButton } from "./ui-button.js";
26
27
  export { StatMeter } from "./stat-meter.js";
27
28
  export { StatusPill } from "./status-pill.js";
@@ -52,6 +53,8 @@ export { KanbanBoard, } from "./kanban-board.js";
52
53
  export { KanbanColumn } from "./kanban-column.js";
53
54
  export { KanbanCard } from "./kanban-card.js";
54
55
  export { TextArea } from "./text-area.js";
56
+ export { LinkCard } from "./link-card.js";
57
+ export { CardGrid } from "./card-grid.js";
55
58
  export { formatDuration } from "./utils/duration.js";
56
59
  export { tokens, tokenValues, darkTokenValues } from "./tokens.js";
57
60
  export * from "./icons.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { AnimateConfetti } from \"./animate-confetti.js\";\nexport { GalleryItem } from \"./gallery-item.js\";\nexport { GalleryItemVariant } from \"./gallery-item-variant.js\";\nexport {\n PhotoGallery,\n type PhotoGalleryChangeReason,\n type PhotoGalleryObjectFit,\n type PhotoGallerySlideChangeDetail,\n} from \"./photo-gallery.js\";\nexport { RevealButton } from \"./reveal-button.js\";\nexport { RomanNumeral } from \"./roman-numeral.js\";\nexport { ConfirmDialog } from \"./confirm-dialog.js\";\nexport { ContentDivider } from \"./content-divider.js\";\nexport {\n ToastNotification,\n notifySuccess,\n notifyError,\n notifyInfo,\n type ToastVariant,\n} from \"./toast-notification.js\";\nexport { SlidePanel } from \"./slide-panel.js\";\nexport { CopyLinkButton } from \"./copy-link-button.js\";\nexport { RelativeTime } from \"./relative-time.js\";\nexport { DistanceValue } from \"./distance-value.js\";\nexport { PriceHistoryChart, type PricePoint } from \"./price-history-chart.js\";\nexport { DistributionChart, type DistributionValue } from \"./distribution-chart.js\";\nexport { PercentBarChart, type PercentBarGroup } from \"./percent-bar-chart.js\";\nexport { WeightBarChart, type WeightBarItem } from \"./weight-bar-chart.js\";\nexport {\n AddressAutocomplete,\n type AddressSuggestion,\n} from \"./address-autocomplete.js\";\nexport {\n AutocompleteInput,\n type AutocompleteOption,\n} from \"./autocomplete-input.js\";\nexport { UserAvatar } from \"./user-avatar.js\";\nexport { MapPin } from \"./map-pin.js\";\nexport { MapCircle } from \"./map-circle.js\";\nexport { RadioCards, type RadioCardOption } from \"./radio-cards.js\";\nexport { RadioPills, type RadioPillOption } from \"./radio-pills.js\";\nexport { UiButton, type ButtonVariant } from \"./ui-button.js\";\nexport { StatMeter } from \"./stat-meter.js\";\nexport { StatusPill, type StatusPillColor } from \"./status-pill.js\";\nexport { EditableText } from \"./editable-text.js\";\nexport { LiveTimer } from \"./live-timer.js\";\nexport {\n ChatMessage,\n type ChatMessageRole,\n type ChatMessageVariant,\n} from \"./chat-message.js\";\nexport { FormSelect, type SelectOption } from \"./form-select.js\";\nexport {\n MultiSelect,\n type MultiSelectOption,\n type MultiSelectVariant,\n} from \"./multi-select.js\";\nexport { DataTable, type DataTableColumn } from \"./data-table.js\";\nexport { TileGrid } from \"./tile-grid.js\";\nexport { PopoverPanel } from \"./popover-panel.js\";\nexport { DropdownButton, type DropdownOption } from \"./dropdown-button.js\";\nexport { IconButton } from \"./icon-button.js\";\nexport { KbdHint, type KbdPlatform } from \"./kbd-hint.js\";\nexport { FrameBox } from \"./frame-box.js\";\nexport { AppShell, type SidebarToggleDetail } from \"./app-shell.js\";\nexport { AppSidebar } from \"./app-sidebar.js\";\nexport { ActionBar } from \"./action-bar.js\";\nexport { PageHeader } from \"./page-header.js\";\nexport { PaginationNav, type PageChangeDetail } from \"./pagination-nav.js\";\nexport { FormActions } from \"./form-actions.js\";\nexport { TimelineContainer } from \"./timeline-container.js\";\nexport { TimelineEntry } from \"./timeline-entry.js\";\nexport { CalendarEntry } from \"./calendar-entry.js\";\nexport { CalendarMonth } from \"./calendar-month.js\";\nexport { CalendarYear } from \"./calendar-year.js\";\nexport {\n KanbanBoard,\n type KanbanCardData,\n type KanbanColumnData,\n type KanbanCardMoveDetail,\n type KanbanCardOpenDetail,\n} from \"./kanban-board.js\";\nexport { KanbanColumn } from \"./kanban-column.js\";\nexport { KanbanCard } from \"./kanban-card.js\";\nexport { TextArea } from \"./text-area.js\";\nexport { formatDuration, type DurationFormat } from \"./utils/duration.js\";\nexport { tokens, tokenValues, darkTokenValues } from \"./tokens.js\";\nexport * from \"./icons.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { AnimateConfetti } from \"./animate-confetti.js\";\nexport { GalleryItem } from \"./gallery-item.js\";\nexport { GalleryItemVariant } from \"./gallery-item-variant.js\";\nexport {\n PhotoGallery,\n type PhotoGalleryChangeReason,\n type PhotoGalleryObjectFit,\n type PhotoGallerySlideChangeDetail,\n} from \"./photo-gallery.js\";\nexport { RevealButton } from \"./reveal-button.js\";\nexport { RomanNumeral } from \"./roman-numeral.js\";\nexport { ConfirmDialog } from \"./confirm-dialog.js\";\nexport { ContentDivider } from \"./content-divider.js\";\nexport {\n ToastNotification,\n notifySuccess,\n notifyError,\n notifyInfo,\n type ToastVariant,\n} from \"./toast-notification.js\";\nexport { SlidePanel } from \"./slide-panel.js\";\nexport { CopyLinkButton } from \"./copy-link-button.js\";\nexport { RelativeTime } from \"./relative-time.js\";\nexport { DistanceValue } from \"./distance-value.js\";\nexport { PriceHistoryChart, type PricePoint } from \"./price-history-chart.js\";\nexport { DistributionChart, type DistributionValue } from \"./distribution-chart.js\";\nexport { PercentBarChart, type PercentBarGroup } from \"./percent-bar-chart.js\";\nexport { WeightBarChart, type WeightBarItem } from \"./weight-bar-chart.js\";\nexport {\n AddressAutocomplete,\n type AddressSuggestion,\n} from \"./address-autocomplete.js\";\nexport {\n AutocompleteInput,\n type AutocompleteOption,\n} from \"./autocomplete-input.js\";\nexport { UserAvatar } from \"./user-avatar.js\";\nexport { MapPin } from \"./map-pin.js\";\nexport { MapCircle } from \"./map-circle.js\";\nexport { RadioCards, type RadioCardOption } from \"./radio-cards.js\";\nexport { RadioPills, type RadioPillOption } from \"./radio-pills.js\";\nexport { ButtonGroup, type ButtonGroupOption } from \"./button-group.js\";\nexport { UiButton, type ButtonVariant } from \"./ui-button.js\";\nexport { StatMeter } from \"./stat-meter.js\";\nexport { StatusPill, type StatusPillColor } from \"./status-pill.js\";\nexport { EditableText } from \"./editable-text.js\";\nexport { LiveTimer } from \"./live-timer.js\";\nexport {\n ChatMessage,\n type ChatMessageRole,\n type ChatMessageVariant,\n} from \"./chat-message.js\";\nexport { FormSelect, type SelectOption } from \"./form-select.js\";\nexport {\n MultiSelect,\n type MultiSelectOption,\n type MultiSelectVariant,\n} from \"./multi-select.js\";\nexport { DataTable, type DataTableColumn } from \"./data-table.js\";\nexport { TileGrid } from \"./tile-grid.js\";\nexport { PopoverPanel } from \"./popover-panel.js\";\nexport { DropdownButton, type DropdownOption } from \"./dropdown-button.js\";\nexport { IconButton } from \"./icon-button.js\";\nexport { KbdHint, type KbdPlatform } from \"./kbd-hint.js\";\nexport { FrameBox } from \"./frame-box.js\";\nexport { AppShell, type SidebarToggleDetail } from \"./app-shell.js\";\nexport { AppSidebar } from \"./app-sidebar.js\";\nexport { ActionBar } from \"./action-bar.js\";\nexport { PageHeader } from \"./page-header.js\";\nexport { PaginationNav, type PageChangeDetail } from \"./pagination-nav.js\";\nexport { FormActions } from \"./form-actions.js\";\nexport { TimelineContainer } from \"./timeline-container.js\";\nexport { TimelineEntry } from \"./timeline-entry.js\";\nexport { CalendarEntry } from \"./calendar-entry.js\";\nexport { CalendarMonth } from \"./calendar-month.js\";\nexport { CalendarYear } from \"./calendar-year.js\";\nexport {\n KanbanBoard,\n type KanbanCardData,\n type KanbanColumnData,\n type KanbanCardMoveDetail,\n type KanbanCardOpenDetail,\n} from \"./kanban-board.js\";\nexport { KanbanColumn } from \"./kanban-column.js\";\nexport { KanbanCard } from \"./kanban-card.js\";\nexport { TextArea } from \"./text-area.js\";\nexport { LinkCard, type LinkCardStatus } from \"./link-card.js\";\nexport { CardGrid } from \"./card-grid.js\";\nexport { formatDuration, type DurationFormat } from \"./utils/duration.js\";\nexport { tokens, tokenValues, darkTokenValues } from \"./tokens.js\";\nexport * from \"./icons.js\";\n"]}
@@ -0,0 +1,34 @@
1
+ import { LitElement } from "lit";
2
+ /** Reachability state for the optional corner status dot. `""` renders no dot. */
3
+ export type LinkCardStatus = "up" | "down" | "checking" | "";
4
+ /**
5
+ * A single linked-resource tile — logo (or an initial-letter fallback),
6
+ * heading, optional description, and an optional reachability status dot.
7
+ * Renders as a real `<a>` (opening in a new tab) when `href` is set, or a
8
+ * non-interactive `<div>` otherwise. Meant to be laid out inside
9
+ * `card-grid`, mirroring how `gallery-item` pairs with `photo-gallery`.
10
+ *
11
+ * @element link-card
12
+ */
13
+ export declare class LinkCard extends LitElement {
14
+ static styles: import("lit").CSSResult[];
15
+ /** Card title. */
16
+ heading: string;
17
+ /** Optional supporting text shown below the heading. */
18
+ description: string;
19
+ /** Destination URL. When set, the card renders as a link (opened in a new tab); when unset, a non-interactive tile. */
20
+ href: string;
21
+ /** Logo image URL. Falls back to the first letter of `heading` if unset or it fails to load. */
22
+ logo: string;
23
+ /** Reachability state for the corner status dot. `""` (default) renders no dot. */
24
+ status: LinkCardStatus;
25
+ private _imgError;
26
+ protected willUpdate(changed: Map<string, unknown>): void;
27
+ render(): import("lit-html").TemplateResult<1>;
28
+ }
29
+ declare global {
30
+ interface HTMLElementTagNameMap {
31
+ "link-card": LinkCard;
32
+ }
33
+ }
34
+ //# sourceMappingURL=link-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-card.d.ts","sourceRoot":"","sources":["../src/link-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAIrD,kFAAkF;AAClF,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,MAAM,GAAG,UAAU,GAAG,EAAE,CAAC;AAQ7D;;;;;;;;GAQG;AACH,qBACa,QAAS,SAAQ,UAAU;IACtC,OAAgB,MAAM,4BA0GpB;IAEF,kBAAkB;IACN,OAAO,SAAM;IACzB,wDAAwD;IAC5C,WAAW,SAAM;IAC7B,uHAAuH;IAC3G,IAAI,SAAM;IACtB,gGAAgG;IACpF,IAAI,SAAM;IACtB,mFAAmF;IACvE,MAAM,EAAE,cAAc,CAAM;IAE/B,OAAO,CAAC,SAAS,CAAS;IAEnC,UAAmB,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,QAE1D;IAEQ,MAAM,yCAuBd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,WAAW,EAAE,QAAQ,CAAC;KACvB;CACF"}
@@ -0,0 +1,197 @@
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, state } from "lit/decorators.js";
9
+ import { tokens } from "./tokens.js";
10
+ const STATUS_LABEL = {
11
+ up: "Reachable",
12
+ down: "Unreachable",
13
+ checking: "Checking…",
14
+ };
15
+ /**
16
+ * A single linked-resource tile — logo (or an initial-letter fallback),
17
+ * heading, optional description, and an optional reachability status dot.
18
+ * Renders as a real `<a>` (opening in a new tab) when `href` is set, or a
19
+ * non-interactive `<div>` otherwise. Meant to be laid out inside
20
+ * `card-grid`, mirroring how `gallery-item` pairs with `photo-gallery`.
21
+ *
22
+ * @element link-card
23
+ */
24
+ let LinkCard = class LinkCard extends LitElement {
25
+ constructor() {
26
+ super(...arguments);
27
+ /** Card title. */
28
+ this.heading = "";
29
+ /** Optional supporting text shown below the heading. */
30
+ this.description = "";
31
+ /** Destination URL. When set, the card renders as a link (opened in a new tab); when unset, a non-interactive tile. */
32
+ this.href = "";
33
+ /** Logo image URL. Falls back to the first letter of `heading` if unset or it fails to load. */
34
+ this.logo = "";
35
+ /** Reachability state for the corner status dot. `""` (default) renders no dot. */
36
+ this.status = "";
37
+ this._imgError = false;
38
+ }
39
+ static { this.styles = [
40
+ tokens,
41
+ css `
42
+ :host {
43
+ display: block;
44
+ font-family: var(
45
+ --ui-font,
46
+ ui-sans-serif,
47
+ system-ui,
48
+ sans-serif,
49
+ "Apple Color Emoji",
50
+ "Segoe UI Emoji",
51
+ "Segoe UI Symbol",
52
+ "Noto Color Emoji"
53
+ );
54
+ }
55
+ .card {
56
+ position: relative;
57
+ display: flex;
58
+ flex-direction: column;
59
+ gap: 0.75rem;
60
+ height: 100%;
61
+ box-sizing: border-box;
62
+ padding: 1.5rem;
63
+ border: 1px solid var(--ui-border, #e2e8f0);
64
+ border-radius: var(--ui-radius, 0.5rem);
65
+ background: var(--ui-surface, #ffffff);
66
+ color: inherit;
67
+ text-decoration: none;
68
+ transition:
69
+ border-color 150ms ease,
70
+ box-shadow 150ms ease,
71
+ transform 150ms ease;
72
+ }
73
+ a.card {
74
+ cursor: pointer;
75
+ }
76
+ .card:hover {
77
+ border-color: var(--ui-text-muted, #64748b);
78
+ box-shadow: var(--ui-shadow, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1));
79
+ transform: translateY(-0.0625rem);
80
+ }
81
+ .card:focus-visible {
82
+ outline: none;
83
+ box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));
84
+ }
85
+ .status {
86
+ position: absolute;
87
+ top: 1.25rem;
88
+ right: 1.25rem;
89
+ width: 0.5rem;
90
+ height: 0.5rem;
91
+ border-radius: 9999px;
92
+ background: var(--ui-text-muted, #64748b);
93
+ }
94
+ .status--up {
95
+ background: var(--ui-success, #16a34a);
96
+ }
97
+ .status--down {
98
+ background: var(--ui-danger, #dc2626);
99
+ }
100
+ .logo {
101
+ display: flex;
102
+ flex: 0 0 auto;
103
+ align-items: center;
104
+ justify-content: center;
105
+ width: 2.5rem;
106
+ height: 2.5rem;
107
+ border-radius: var(--ui-radius, 0.5rem);
108
+ background: var(--ui-surface-muted, #f8fafc);
109
+ overflow: hidden;
110
+ }
111
+ .logo img {
112
+ width: 100%;
113
+ height: 100%;
114
+ object-fit: contain;
115
+ }
116
+ .initial {
117
+ font-size: var(--ui-font-size-lg, 1rem);
118
+ font-weight: var(--ui-font-weight-semibold, 600);
119
+ color: var(--ui-text-muted, #64748b);
120
+ }
121
+ .heading {
122
+ font-size: var(--ui-font-size-lg, 1rem);
123
+ font-weight: var(--ui-font-weight-semibold, 600);
124
+ line-height: var(--ui-line-height-tight, 1.25);
125
+ color: var(--ui-text, #0f172a);
126
+ }
127
+ .description {
128
+ font-size: var(--ui-font-size, 0.875rem);
129
+ line-height: var(--ui-line-height-normal, 1.5);
130
+ color: var(--ui-text-muted, #64748b);
131
+ }
132
+ @media (forced-colors: active) {
133
+ .card:focus-visible {
134
+ outline: 2px solid CanvasText;
135
+ outline-offset: 2px;
136
+ box-shadow: none;
137
+ }
138
+ }
139
+ @media (prefers-reduced-motion: reduce) {
140
+ .card {
141
+ transition: none;
142
+ }
143
+ }
144
+ `,
145
+ ]; }
146
+ willUpdate(changed) {
147
+ if (changed.has("logo"))
148
+ this._imgError = false;
149
+ }
150
+ render() {
151
+ const showImage = !!this.logo && !this._imgError;
152
+ const initial = this.heading.trim().charAt(0).toUpperCase();
153
+ const body = html `
154
+ ${this.status
155
+ ? html `<span
156
+ class="status status--${this.status}"
157
+ role="img"
158
+ title=${STATUS_LABEL[this.status]}
159
+ aria-label=${STATUS_LABEL[this.status]}
160
+ ></span>`
161
+ : nothing}
162
+ <span class="logo">
163
+ ${showImage
164
+ ? html `<img src=${this.logo} alt="" @error=${() => (this._imgError = true)} />`
165
+ : html `<span class="initial" aria-hidden="true">${initial}</span>`}
166
+ </span>
167
+ <span class="heading">${this.heading}</span>
168
+ ${this.description ? html `<span class="description">${this.description}</span>` : nothing}
169
+ `;
170
+ return this.href
171
+ ? html `<a class="card" href=${this.href} target="_blank" rel="noopener noreferrer">${body}</a>`
172
+ : html `<div class="card">${body}</div>`;
173
+ }
174
+ };
175
+ __decorate([
176
+ property()
177
+ ], LinkCard.prototype, "heading", void 0);
178
+ __decorate([
179
+ property()
180
+ ], LinkCard.prototype, "description", void 0);
181
+ __decorate([
182
+ property()
183
+ ], LinkCard.prototype, "href", void 0);
184
+ __decorate([
185
+ property()
186
+ ], LinkCard.prototype, "logo", void 0);
187
+ __decorate([
188
+ property()
189
+ ], LinkCard.prototype, "status", void 0);
190
+ __decorate([
191
+ state()
192
+ ], LinkCard.prototype, "_imgError", void 0);
193
+ LinkCard = __decorate([
194
+ customElement("link-card")
195
+ ], LinkCard);
196
+ export { LinkCard };
197
+ //# sourceMappingURL=link-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link-card.js","sourceRoot":"","sources":["../src/link-card.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAKrC,MAAM,YAAY,GAAgD;IAChE,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,aAAa;IACnB,QAAQ,EAAE,WAAW;CACtB,CAAC;AAEF;;;;;;;;GAQG;AAEI,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,UAAU;IAAjC;;QA6GL,kBAAkB;QACN,YAAO,GAAG,EAAE,CAAC;QACzB,wDAAwD;QAC5C,gBAAW,GAAG,EAAE,CAAC;QAC7B,uHAAuH;QAC3G,SAAI,GAAG,EAAE,CAAC;QACtB,gGAAgG;QACpF,SAAI,GAAG,EAAE,CAAC;QACtB,mFAAmF;QACvE,WAAM,GAAmB,EAAE,CAAC;QAEvB,cAAS,GAAG,KAAK,CAAC;IA8BrC,CAAC;aArJiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuGF;KACF,AA1GqB,CA0GpB;IAeiB,UAAU,CAAC,OAA6B;QACzD,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IAClD,CAAC;IAEQ,MAAM;QACb,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAA;QACb,IAAI,CAAC,MAAM;YACX,CAAC,CAAC,IAAI,CAAA;oCACsB,IAAI,CAAC,MAAM;;oBAE3B,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;yBACpB,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;mBAC/B;YACX,CAAC,CAAC,OAAO;;UAEP,SAAS;YACT,CAAC,CAAC,IAAI,CAAA,YAAY,IAAI,CAAC,IAAI,kBAAkB,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK;YAC/E,CAAC,CAAC,IAAI,CAAA,4CAA4C,OAAO,SAAS;;8BAE9C,IAAI,CAAC,OAAO;QAClC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA,6BAA6B,IAAI,CAAC,WAAW,SAAS,CAAC,CAAC,CAAC,OAAO;KAC1F,CAAC;QACF,OAAO,IAAI,CAAC,IAAI;YACd,CAAC,CAAC,IAAI,CAAA,wBAAwB,IAAI,CAAC,IAAI,8CAA8C,IAAI,MAAM;YAC/F,CAAC,CAAC,IAAI,CAAA,qBAAqB,IAAI,QAAQ,CAAC;IAC5C,CAAC;CACF,CAAA;AAxCa;IAAX,QAAQ,EAAE;yCAAc;AAEb;IAAX,QAAQ,EAAE;6CAAkB;AAEjB;IAAX,QAAQ,EAAE;sCAAW;AAEV;IAAX,QAAQ,EAAE;sCAAW;AAEV;IAAX,QAAQ,EAAE;wCAA6B;AAEvB;IAAhB,KAAK,EAAE;2CAA2B;AAxHxB,QAAQ;IADpB,aAAa,CAAC,WAAW,CAAC;GACd,QAAQ,CAsJpB","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\n\n/** Reachability state for the optional corner status dot. `\"\"` renders no dot. */\nexport type LinkCardStatus = \"up\" | \"down\" | \"checking\" | \"\";\n\nconst STATUS_LABEL: Record<Exclude<LinkCardStatus, \"\">, string> = {\n up: \"Reachable\",\n down: \"Unreachable\",\n checking: \"Checking…\",\n};\n\n/**\n * A single linked-resource tile — logo (or an initial-letter fallback),\n * heading, optional description, and an optional reachability status dot.\n * Renders as a real `<a>` (opening in a new tab) when `href` is set, or a\n * non-interactive `<div>` otherwise. Meant to be laid out inside\n * `card-grid`, mirroring how `gallery-item` pairs with `photo-gallery`.\n *\n * @element link-card\n */\n@customElement(\"link-card\")\nexport class LinkCard extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n }\n .card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n height: 100%;\n box-sizing: border-box;\n padding: 1.5rem;\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius, 0.5rem);\n background: var(--ui-surface, #ffffff);\n color: inherit;\n text-decoration: none;\n transition:\n border-color 150ms ease,\n box-shadow 150ms ease,\n transform 150ms ease;\n }\n a.card {\n cursor: pointer;\n }\n .card:hover {\n border-color: var(--ui-text-muted, #64748b);\n box-shadow: var(--ui-shadow, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1));\n transform: translateY(-0.0625rem);\n }\n .card:focus-visible {\n outline: none;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .status {\n position: absolute;\n top: 1.25rem;\n right: 1.25rem;\n width: 0.5rem;\n height: 0.5rem;\n border-radius: 9999px;\n background: var(--ui-text-muted, #64748b);\n }\n .status--up {\n background: var(--ui-success, #16a34a);\n }\n .status--down {\n background: var(--ui-danger, #dc2626);\n }\n .logo {\n display: flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n border-radius: var(--ui-radius, 0.5rem);\n background: var(--ui-surface-muted, #f8fafc);\n overflow: hidden;\n }\n .logo img {\n width: 100%;\n height: 100%;\n object-fit: contain;\n }\n .initial {\n font-size: var(--ui-font-size-lg, 1rem);\n font-weight: var(--ui-font-weight-semibold, 600);\n color: var(--ui-text-muted, #64748b);\n }\n .heading {\n font-size: var(--ui-font-size-lg, 1rem);\n font-weight: var(--ui-font-weight-semibold, 600);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text, #0f172a);\n }\n .description {\n font-size: var(--ui-font-size, 0.875rem);\n line-height: var(--ui-line-height-normal, 1.5);\n color: var(--ui-text-muted, #64748b);\n }\n @media (forced-colors: active) {\n .card:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .card {\n transition: none;\n }\n }\n `,\n ];\n\n /** Card title. */\n @property() heading = \"\";\n /** Optional supporting text shown below the heading. */\n @property() description = \"\";\n /** Destination URL. When set, the card renders as a link (opened in a new tab); when unset, a non-interactive tile. */\n @property() href = \"\";\n /** Logo image URL. Falls back to the first letter of `heading` if unset or it fails to load. */\n @property() logo = \"\";\n /** Reachability state for the corner status dot. `\"\"` (default) renders no dot. */\n @property() status: LinkCardStatus = \"\";\n\n @state() private _imgError = false;\n\n protected override willUpdate(changed: Map<string, unknown>) {\n if (changed.has(\"logo\")) this._imgError = false;\n }\n\n override render() {\n const showImage = !!this.logo && !this._imgError;\n const initial = this.heading.trim().charAt(0).toUpperCase();\n const body = html`\n ${this.status\n ? html`<span\n class=\"status status--${this.status}\"\n role=\"img\"\n title=${STATUS_LABEL[this.status]}\n aria-label=${STATUS_LABEL[this.status]}\n ></span>`\n : nothing}\n <span class=\"logo\">\n ${showImage\n ? html`<img src=${this.logo} alt=\"\" @error=${() => (this._imgError = true)} />`\n : html`<span class=\"initial\" aria-hidden=\"true\">${initial}</span>`}\n </span>\n <span class=\"heading\">${this.heading}</span>\n ${this.description ? html`<span class=\"description\">${this.description}</span>` : nothing}\n `;\n return this.href\n ? html`<a class=\"card\" href=${this.href} target=\"_blank\" rel=\"noopener noreferrer\">${body}</a>`\n : html`<div class=\"card\">${body}</div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"link-card\": LinkCard;\n }\n}\n"]}
@@ -15,6 +15,8 @@ export declare class StatMeter extends LitElement {
15
15
  percent: number | null;
16
16
  /** Fill color override; falls back to the `--ui-success` token. */
17
17
  color: string;
18
+ /** Track (inactive portion) background override; falls back to the `--ui-surface-muted` token. */
19
+ trackColor: string;
18
20
  render(): import("lit-html").TemplateResult<1>;
19
21
  }
20
22
  declare global {
@@ -1 +1 @@
1
- {"version":3,"file":"stat-meter.d.ts","sourceRoot":"","sources":["../src/stat-meter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C;;;;;;;GAOG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC,OAAgB,MAAM,4BA6DpB;IAEF,6DAA6D;IACjD,KAAK,SAAM;IAEvB,qFAAqF;IACzD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1D,mEAAmE;IACvD,KAAK,SAAM;IAEd,MAAM,yCAWd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
1
+ {"version":3,"file":"stat-meter.d.ts","sourceRoot":"","sources":["../src/stat-meter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C;;;;;;;GAOG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC,OAAgB,MAAM,4BA6DpB;IAEF,6DAA6D;IACjD,KAAK,SAAM;IAEvB,qFAAqF;IACzD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1D,mEAAmE;IACvD,KAAK,SAAM;IAEvB,kGAAkG;IAC1D,UAAU,SAAM;IAE/C,MAAM,yCAYd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,SAAS,CAAC;KACzB;CACF"}
@@ -24,6 +24,8 @@ let StatMeter = class StatMeter extends LitElement {
24
24
  this.percent = null;
25
25
  /** Fill color override; falls back to the `--ui-success` token. */
26
26
  this.color = "";
27
+ /** Track (inactive portion) background override; falls back to the `--ui-surface-muted` token. */
28
+ this.trackColor = "";
27
29
  }
28
30
  static { this.styles = [
29
31
  tokens,
@@ -56,7 +58,7 @@ let StatMeter = class StatMeter extends LitElement {
56
58
  width: 4rem;
57
59
  height: 0.375rem;
58
60
  border-radius: 9999px;
59
- background: var(--ui-surface-muted, #f8fafc);
61
+ background: var(--track-color, var(--ui-surface-muted, #f8fafc));
60
62
  overflow: hidden;
61
63
  }
62
64
 
@@ -91,9 +93,10 @@ let StatMeter = class StatMeter extends LitElement {
91
93
  const pct = this.percent;
92
94
  const clamped = pct === null ? 0 : Math.min(100, Math.max(0, pct));
93
95
  const fillStyle = this.color ? `width: ${clamped}%; --fill-color: ${this.color}` : `width: ${clamped}%`;
96
+ const trackStyle = this.trackColor ? `--track-color: ${this.trackColor}` : "";
94
97
  return html `
95
98
  <span class="label">${this.label}</span>
96
- <span class="track" role="img" aria-label="${this.label} ${pct === null ? "no reading" : `${pct}%`}">
99
+ <span class="track" role="img" style=${trackStyle} aria-label="${this.label} ${pct === null ? "no reading" : `${pct}%`}">
97
100
  <span class="fill" style=${fillStyle}></span>
98
101
  </span>
99
102
  <span class="value">${pct === null ? "—" : `${pct}%`}</span>
@@ -109,6 +112,9 @@ __decorate([
109
112
  __decorate([
110
113
  property()
111
114
  ], StatMeter.prototype, "color", void 0);
115
+ __decorate([
116
+ property({ attribute: "track-color" })
117
+ ], StatMeter.prototype, "trackColor", void 0);
112
118
  StatMeter = __decorate([
113
119
  customElement("stat-meter")
114
120
  ], StatMeter);
@@ -1 +1 @@
1
- {"version":3,"file":"stat-meter.js","sourceRoot":"","sources":["../src/stat-meter.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;AAErC;;;;;;;GAOG;AAEI,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,UAAU;IAAlC;;QAgEL,6DAA6D;QACjD,UAAK,GAAG,EAAE,CAAC;QAEvB,qFAAqF;QACzD,YAAO,GAAkB,IAAI,CAAC;QAE1D,mEAAmE;QACvD,UAAK,GAAG,EAAE,CAAC;IAczB,CAAC;aApFiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0DF;KACF,AA7DqB,CA6DpB;IAWO,MAAM;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;QACzB,MAAM,OAAO,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACnE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,OAAO,oBAAoB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,UAAU,OAAO,GAAG,CAAC;QACxG,OAAO,IAAI,CAAA;4BACa,IAAI,CAAC,KAAK;mDACa,IAAI,CAAC,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG;mCACrE,SAAS;;4BAEhB,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG;KACrD,CAAC;IACJ,CAAC;CACF,CAAA;AApBa;IAAX,QAAQ,EAAE;wCAAY;AAGK;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAA+B;AAG9C;IAAX,QAAQ,EAAE;wCAAY;AAvEZ,SAAS;IADrB,aAAa,CAAC,YAAY,CAAC;GACf,SAAS,CAqFrB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * A compact labeled meter for a single percentage reading — e.g. CPU or\n * memory usage in a dashboard header. `percent` may be `null` when no\n * reading is available yet (e.g. the first tick of a polling metric); the\n * bar then renders empty and the value shows an em dash instead of \"0%\".\n *\n * @element stat-meter\n */\n@customElement(\"stat-meter\")\nexport class StatMeter extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n }\n\n .label {\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: var(--ui-font-weight-semibold, 600);\n letter-spacing: var(--ui-tracking-wide, 0.04em);\n color: var(--ui-text-muted, #64748b);\n }\n\n .track {\n display: block;\n width: 4rem;\n height: 0.375rem;\n border-radius: 9999px;\n background: var(--ui-surface-muted, #f8fafc);\n overflow: hidden;\n }\n\n .fill {\n display: block;\n height: 100%;\n /* Keep the top highlight while softening the dark edge for compact meters. */\n background: linear-gradient(\n to bottom,\n color-mix(in srgb, var(--fill-color, var(--ui-success, #16a34a)) 70%, #ffffff) 0%,\n color-mix(in srgb, var(--fill-color, var(--ui-success, #16a34a)) 80%, #000000) 100%\n );\n transition: width 200ms ease;\n }\n\n .value {\n min-width: 2rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: var(--ui-font-weight-medium, 500);\n color: var(--ui-text, #0f172a);\n font-variant-numeric: tabular-nums;\n text-align: right;\n }\n @media (prefers-reduced-motion: reduce) {\n .fill {\n transition: none;\n }\n }\n `,\n ];\n\n /** Short label shown before the bar, e.g. \"CPU\" or \"MEM\". */\n @property() label = \"\";\n\n /** Percentage 0-100. `null` renders an empty bar and a \"—\" value instead of \"0%\". */\n @property({ type: Number }) percent: number | null = null;\n\n /** Fill color override; falls back to the `--ui-success` token. */\n @property() color = \"\";\n\n override render() {\n const pct = this.percent;\n const clamped = pct === null ? 0 : Math.min(100, Math.max(0, pct));\n const fillStyle = this.color ? `width: ${clamped}%; --fill-color: ${this.color}` : `width: ${clamped}%`;\n return html`\n <span class=\"label\">${this.label}</span>\n <span class=\"track\" role=\"img\" aria-label=\"${this.label} ${pct === null ? \"no reading\" : `${pct}%`}\">\n <span class=\"fill\" style=${fillStyle}></span>\n </span>\n <span class=\"value\">${pct === null ? \"—\" : `${pct}%`}</span>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"stat-meter\": StatMeter;\n }\n}\n"]}
1
+ {"version":3,"file":"stat-meter.js","sourceRoot":"","sources":["../src/stat-meter.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;AAErC;;;;;;;GAOG;AAEI,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,UAAU;IAAlC;;QAgEL,6DAA6D;QACjD,UAAK,GAAG,EAAE,CAAC;QAEvB,qFAAqF;QACzD,YAAO,GAAkB,IAAI,CAAC;QAE1D,mEAAmE;QACvD,UAAK,GAAG,EAAE,CAAC;QAEvB,kGAAkG;QAC1D,eAAU,GAAG,EAAE,CAAC;IAe1D,CAAC;aAxFiB,WAAM,GAAG;QACvB,MAAM;QACN,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0DF;KACF,AA7DqB,CA6DpB;IAcO,MAAM;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC;QACzB,MAAM,OAAO,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACnE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,OAAO,oBAAoB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,UAAU,OAAO,GAAG,CAAC;QACxG,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,kBAAkB,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,OAAO,IAAI,CAAA;4BACa,IAAI,CAAC,KAAK;6CACO,UAAU,gBAAgB,IAAI,CAAC,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG;mCACzF,SAAS;;4BAEhB,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG;KACrD,CAAC;IACJ,CAAC;CACF,CAAA;AAxBa;IAAX,QAAQ,EAAE;wCAAY;AAGK;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0CAA+B;AAG9C;IAAX,QAAQ,EAAE;wCAAY;AAGiB;IAAvC,QAAQ,CAAC,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;6CAAiB;AA1E7C,SAAS;IADrB,aAAa,CAAC,YAAY,CAAC;GACf,SAAS,CAyFrB","sourcesContent":["import { LitElement, css, html } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * A compact labeled meter for a single percentage reading — e.g. CPU or\n * memory usage in a dashboard header. `percent` may be `null` when no\n * reading is available yet (e.g. the first tick of a polling metric); the\n * bar then renders empty and the value shows an em dash instead of \"0%\".\n *\n * @element stat-meter\n */\n@customElement(\"stat-meter\")\nexport class StatMeter extends LitElement {\n static override styles = [\n tokens,\n css`\n :host {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n }\n\n .label {\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: var(--ui-font-weight-semibold, 600);\n letter-spacing: var(--ui-tracking-wide, 0.04em);\n color: var(--ui-text-muted, #64748b);\n }\n\n .track {\n display: block;\n width: 4rem;\n height: 0.375rem;\n border-radius: 9999px;\n background: var(--track-color, var(--ui-surface-muted, #f8fafc));\n overflow: hidden;\n }\n\n .fill {\n display: block;\n height: 100%;\n /* Keep the top highlight while softening the dark edge for compact meters. */\n background: linear-gradient(\n to bottom,\n color-mix(in srgb, var(--fill-color, var(--ui-success, #16a34a)) 70%, #ffffff) 0%,\n color-mix(in srgb, var(--fill-color, var(--ui-success, #16a34a)) 80%, #000000) 100%\n );\n transition: width 200ms ease;\n }\n\n .value {\n min-width: 2rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-weight: var(--ui-font-weight-medium, 500);\n color: var(--ui-text, #0f172a);\n font-variant-numeric: tabular-nums;\n text-align: right;\n }\n @media (prefers-reduced-motion: reduce) {\n .fill {\n transition: none;\n }\n }\n `,\n ];\n\n /** Short label shown before the bar, e.g. \"CPU\" or \"MEM\". */\n @property() label = \"\";\n\n /** Percentage 0-100. `null` renders an empty bar and a \"—\" value instead of \"0%\". */\n @property({ type: Number }) percent: number | null = null;\n\n /** Fill color override; falls back to the `--ui-success` token. */\n @property() color = \"\";\n\n /** Track (inactive portion) background override; falls back to the `--ui-surface-muted` token. */\n @property({ attribute: \"track-color\" }) trackColor = \"\";\n\n override render() {\n const pct = this.percent;\n const clamped = pct === null ? 0 : Math.min(100, Math.max(0, pct));\n const fillStyle = this.color ? `width: ${clamped}%; --fill-color: ${this.color}` : `width: ${clamped}%`;\n const trackStyle = this.trackColor ? `--track-color: ${this.trackColor}` : \"\";\n return html`\n <span class=\"label\">${this.label}</span>\n <span class=\"track\" role=\"img\" style=${trackStyle} aria-label=\"${this.label} ${pct === null ? \"no reading\" : `${pct}%`}\">\n <span class=\"fill\" style=${fillStyle}></span>\n </span>\n <span class=\"value\">${pct === null ? \"—\" : `${pct}%`}</span>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"stat-meter\": StatMeter;\n }\n}\n"]}
@@ -0,0 +1,64 @@
1
+ # `<button-group>`
2
+
3
+ Single-select segmented control — a strip of buttons joined into one
4
+ shared-border shape, for a small, persistent set of mutually exclusive
5
+ choices (a view switcher, a theme picker) where the *currently selected*
6
+ option should read as visually "pressed," not just checked. For many
7
+ short, individually pill-shaped choices, use `radio-pills` instead. Wraps
8
+ native radio inputs for keyboard/a11y and fires `change` rather than
9
+ relying on form submission.
10
+
11
+ ## Install
12
+
13
+ ```js
14
+ import "@f-ewald/components/button-group.js";
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```html
20
+ <button-group></button-group>
21
+ <script type="module">
22
+ const el = document.querySelector("button-group");
23
+ el.options = [
24
+ { value: "list", label: "List" },
25
+ { value: "kanban", label: "Kanban" },
26
+ ];
27
+ el.value = "list";
28
+ el.addEventListener("change", (e) => console.log(e.detail.value));
29
+ </script>
30
+ ```
31
+
32
+ ## Attributes / properties
33
+
34
+ | Property | Attribute | Type | Default | Description |
35
+ | --- | --- | --- | --- | --- |
36
+ | `options` | _(JS property only)_ | `ButtonGroupOption[]` | `[]` | Options to render, one segment each. |
37
+ | `value` | `value` | `string` | `""` | Currently selected value. |
38
+ | `disabled` | `disabled` | `boolean` | `false` | Disables every native radio in the group. |
39
+
40
+ ## Events
41
+
42
+ | Event | Description |
43
+ | --- | --- |
44
+ | `change` | A segment was selected; detail: { value }. |
45
+
46
+ ## Slots
47
+
48
+ _None._
49
+
50
+ ## CSS custom properties
51
+
52
+ | Custom property |
53
+ | --- |
54
+ | `--ui-border` |
55
+ | `--ui-focus-ring` |
56
+ | `--ui-font` |
57
+ | `--ui-font-size-sm` |
58
+ | `--ui-font-weight-medium` |
59
+ | `--ui-line-height-tight` |
60
+ | `--ui-on-accent` |
61
+ | `--ui-primary` |
62
+ | `--ui-radius-sm` |
63
+ | `--ui-surface-muted` |
64
+ | `--ui-text` |
@@ -0,0 +1,44 @@
1
+ # `<card-grid>`
2
+
3
+ A responsive auto-filling grid shell for `link-card` (or any card-shaped
4
+ content) — each slotted child becomes a grid item, wrapping to a new row
5
+ once the container is too narrow for another `15rem` column.
6
+
7
+ ## Install
8
+
9
+ ```js
10
+ import "@f-ewald/components/card-grid.js";
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```html
16
+ <card-grid>
17
+ <link-card
18
+ heading="Grafana"
19
+ description="Metrics dashboards."
20
+ href="https://grafana.example.com"
21
+ logo="/logos/grafana.svg"
22
+ status="up"
23
+ ></link-card>
24
+ <link-card heading="Plex" description="Media server." href="https://plex.example.com" status="up"></link-card>
25
+ </card-grid>
26
+ ```
27
+
28
+ ## Attributes / properties
29
+
30
+ _None._
31
+
32
+ ## Events
33
+
34
+ _None._
35
+
36
+ ## Slots
37
+
38
+ | Slot | Description |
39
+ | --- | --- |
40
+ | `(default)` | `link-card` elements (or other card-shaped content). |
41
+
42
+ ## CSS custom properties
43
+
44
+ _None._
@@ -0,0 +1,65 @@
1
+ # `<link-card>`
2
+
3
+ A single linked-resource tile — logo (or an initial-letter fallback),
4
+ heading, optional description, and an optional reachability status dot.
5
+ Renders as a real `<a>` (opening in a new tab) when `href` is set, or a
6
+ non-interactive `<div>` otherwise. Meant to be laid out inside
7
+ `card-grid`, mirroring how `gallery-item` pairs with `photo-gallery`.
8
+
9
+ ## Install
10
+
11
+ ```js
12
+ import "@f-ewald/components/link-card.js";
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```html
18
+ <link-card
19
+ heading="Grafana"
20
+ description="Metrics dashboards."
21
+ href="https://grafana.example.com"
22
+ logo="/logos/grafana.svg"
23
+ status="up"
24
+ ></link-card>
25
+ <link-card heading="Backup Server" description="Nightly restic snapshots." status="checking"></link-card>
26
+ ```
27
+
28
+ ## Attributes / properties
29
+
30
+ | Property | Attribute | Type | Default | Description |
31
+ | --- | --- | --- | --- | --- |
32
+ | `heading` | `heading` | `string` | `""` | Card title. |
33
+ | `description` | `description` | `string` | `""` | Optional supporting text shown below the heading. |
34
+ | `href` | `href` | `string` | `""` | Destination URL. When set, the card renders as a link (opened in a new tab); when unset, a non-interactive tile. |
35
+ | `logo` | `logo` | `string` | `""` | Logo image URL. Falls back to the first letter of `heading` if unset or it fails to load. |
36
+ | `status` | `status` | `LinkCardStatus` | `""` | Reachability state for the corner status dot. `""` (default) renders no dot. |
37
+
38
+ ## Events
39
+
40
+ _None._
41
+
42
+ ## Slots
43
+
44
+ _None._
45
+
46
+ ## CSS custom properties
47
+
48
+ | Custom property |
49
+ | --- |
50
+ | `--ui-border` |
51
+ | `--ui-danger` |
52
+ | `--ui-focus-ring` |
53
+ | `--ui-font` |
54
+ | `--ui-font-size` |
55
+ | `--ui-font-size-lg` |
56
+ | `--ui-font-weight-semibold` |
57
+ | `--ui-line-height-normal` |
58
+ | `--ui-line-height-tight` |
59
+ | `--ui-radius` |
60
+ | `--ui-shadow` |
61
+ | `--ui-success` |
62
+ | `--ui-surface` |
63
+ | `--ui-surface-muted` |
64
+ | `--ui-text` |
65
+ | `--ui-text-muted` |