@xmesh/system-design 0.0.1

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 (175) hide show
  1. package/README.md +472 -0
  2. package/assets/brand-lockup-dark.svg +9 -0
  3. package/assets/brand-lockup-light.svg +9 -0
  4. package/assets/brand-mark.svg +9 -0
  5. package/colors_and_type.css +11 -0
  6. package/dist/lit/components/alert/index.css +201 -0
  7. package/dist/lit/components/alert/index.d.ts +25 -0
  8. package/dist/lit/components/alert/index.js +191 -0
  9. package/dist/lit/components/app-bar/index.css +80 -0
  10. package/dist/lit/components/app-bar/index.d.ts +19 -0
  11. package/dist/lit/components/app-bar/index.js +120 -0
  12. package/dist/lit/components/artifact/index.css +166 -0
  13. package/dist/lit/components/artifact/index.d.ts +37 -0
  14. package/dist/lit/components/artifact/index.js +294 -0
  15. package/dist/lit/components/autocomplete/index.css +171 -0
  16. package/dist/lit/components/autocomplete/index.d.ts +47 -0
  17. package/dist/lit/components/autocomplete/index.js +404 -0
  18. package/dist/lit/components/avatar/index.css +62 -0
  19. package/dist/lit/components/avatar/index.d.ts +19 -0
  20. package/dist/lit/components/avatar/index.js +112 -0
  21. package/dist/lit/components/avatar-group/index.css +60 -0
  22. package/dist/lit/components/avatar-group/index.d.ts +19 -0
  23. package/dist/lit/components/avatar-group/index.js +97 -0
  24. package/dist/lit/components/badge/index.css +72 -0
  25. package/dist/lit/components/badge/index.d.ts +18 -0
  26. package/dist/lit/components/badge/index.js +115 -0
  27. package/dist/lit/components/brand-mark/index.css +109 -0
  28. package/dist/lit/components/brand-mark/index.d.ts +24 -0
  29. package/dist/lit/components/brand-mark/index.js +116 -0
  30. package/dist/lit/components/breadcrumbs/index.css +91 -0
  31. package/dist/lit/components/breadcrumbs/index.d.ts +19 -0
  32. package/dist/lit/components/breadcrumbs/index.js +104 -0
  33. package/dist/lit/components/bubble/index.css +182 -0
  34. package/dist/lit/components/bubble/index.d.ts +72 -0
  35. package/dist/lit/components/bubble/index.js +617 -0
  36. package/dist/lit/components/button/index.css +342 -0
  37. package/dist/lit/components/button/index.d.ts +32 -0
  38. package/dist/lit/components/button/index.js +202 -0
  39. package/dist/lit/components/card/index.css +99 -0
  40. package/dist/lit/components/card/index.d.ts +20 -0
  41. package/dist/lit/components/card/index.js +133 -0
  42. package/dist/lit/components/chat/index.css +292 -0
  43. package/dist/lit/components/chat/index.d.ts +74 -0
  44. package/dist/lit/components/chat/index.js +589 -0
  45. package/dist/lit/components/checkbox/index.css +126 -0
  46. package/dist/lit/components/checkbox/index.d.ts +21 -0
  47. package/dist/lit/components/checkbox/index.js +138 -0
  48. package/dist/lit/components/chip/index.css +145 -0
  49. package/dist/lit/components/chip/index.d.ts +30 -0
  50. package/dist/lit/components/chip/index.js +230 -0
  51. package/dist/lit/components/chip-group/index.css +19 -0
  52. package/dist/lit/components/chip-group/index.d.ts +24 -0
  53. package/dist/lit/components/chip-group/index.js +171 -0
  54. package/dist/lit/components/code/index.css +42 -0
  55. package/dist/lit/components/code/index.d.ts +12 -0
  56. package/dist/lit/components/code/index.js +68 -0
  57. package/dist/lit/components/composer/index.css +548 -0
  58. package/dist/lit/components/composer/index.d.ts +67 -0
  59. package/dist/lit/components/composer/index.js +713 -0
  60. package/dist/lit/components/data-table/index.css +166 -0
  61. package/dist/lit/components/data-table/index.d.ts +55 -0
  62. package/dist/lit/components/data-table/index.js +390 -0
  63. package/dist/lit/components/dialog/index.css +124 -0
  64. package/dist/lit/components/dialog/index.d.ts +24 -0
  65. package/dist/lit/components/dialog/index.js +199 -0
  66. package/dist/lit/components/divider/index.css +27 -0
  67. package/dist/lit/components/divider/index.d.ts +13 -0
  68. package/dist/lit/components/divider/index.js +67 -0
  69. package/dist/lit/components/empty-state/index.css +69 -0
  70. package/dist/lit/components/empty-state/index.d.ts +21 -0
  71. package/dist/lit/components/empty-state/index.js +123 -0
  72. package/dist/lit/components/expansion-panel/index.css +120 -0
  73. package/dist/lit/components/expansion-panel/index.d.ts +22 -0
  74. package/dist/lit/components/expansion-panel/index.js +174 -0
  75. package/dist/lit/components/field/index.css +223 -0
  76. package/dist/lit/components/field/index.d.ts +106 -0
  77. package/dist/lit/components/field/index.js +388 -0
  78. package/dist/lit/components/file-input/index.css +257 -0
  79. package/dist/lit/components/file-input/index.d.ts +30 -0
  80. package/dist/lit/components/file-input/index.js +298 -0
  81. package/dist/lit/components/form/index.css +29 -0
  82. package/dist/lit/components/form/index.d.ts +38 -0
  83. package/dist/lit/components/form/index.js +192 -0
  84. package/dist/lit/components/grid/index.css +53 -0
  85. package/dist/lit/components/grid/index.d.ts +14 -0
  86. package/dist/lit/components/grid/index.js +82 -0
  87. package/dist/lit/components/kbd/index.css +35 -0
  88. package/dist/lit/components/kbd/index.d.ts +11 -0
  89. package/dist/lit/components/kbd/index.js +43 -0
  90. package/dist/lit/components/list/index.css +15 -0
  91. package/dist/lit/components/list/index.d.ts +28 -0
  92. package/dist/lit/components/list/index.js +188 -0
  93. package/dist/lit/components/list-item/index.css +119 -0
  94. package/dist/lit/components/list-item/index.d.ts +20 -0
  95. package/dist/lit/components/list-item/index.js +127 -0
  96. package/dist/lit/components/menu/index.css +94 -0
  97. package/dist/lit/components/menu/index.d.ts +47 -0
  98. package/dist/lit/components/menu/index.js +386 -0
  99. package/dist/lit/components/navigation-drawer/index.css +114 -0
  100. package/dist/lit/components/navigation-drawer/index.d.ts +29 -0
  101. package/dist/lit/components/navigation-drawer/index.js +218 -0
  102. package/dist/lit/components/overlay/index.css +171 -0
  103. package/dist/lit/components/overlay/index.d.ts +65 -0
  104. package/dist/lit/components/overlay/index.js +566 -0
  105. package/dist/lit/components/pagination/index.css +102 -0
  106. package/dist/lit/components/pagination/index.d.ts +22 -0
  107. package/dist/lit/components/pagination/index.js +184 -0
  108. package/dist/lit/components/primitives/index.css +504 -0
  109. package/dist/lit/components/primitives/index.d.ts +25 -0
  110. package/dist/lit/components/primitives/index.js +283 -0
  111. package/dist/lit/components/progress/index.css +143 -0
  112. package/dist/lit/components/progress/index.d.ts +23 -0
  113. package/dist/lit/components/progress/index.js +180 -0
  114. package/dist/lit/components/radio-group/index.css +178 -0
  115. package/dist/lit/components/radio-group/index.d.ts +35 -0
  116. package/dist/lit/components/radio-group/index.js +292 -0
  117. package/dist/lit/components/select/index.css +151 -0
  118. package/dist/lit/components/select/index.d.ts +50 -0
  119. package/dist/lit/components/select/index.js +390 -0
  120. package/dist/lit/components/sidebar-item/index.css +133 -0
  121. package/dist/lit/components/sidebar-item/index.d.ts +20 -0
  122. package/dist/lit/components/sidebar-item/index.js +105 -0
  123. package/dist/lit/components/skeleton/index.css +81 -0
  124. package/dist/lit/components/skeleton/index.d.ts +19 -0
  125. package/dist/lit/components/skeleton/index.js +119 -0
  126. package/dist/lit/components/slider/index.css +171 -0
  127. package/dist/lit/components/slider/index.d.ts +36 -0
  128. package/dist/lit/components/slider/index.js +302 -0
  129. package/dist/lit/components/snackbar/index.css +279 -0
  130. package/dist/lit/components/snackbar/index.d.ts +33 -0
  131. package/dist/lit/components/snackbar/index.js +195 -0
  132. package/dist/lit/components/stack/index.css +41 -0
  133. package/dist/lit/components/stack/index.d.ts +20 -0
  134. package/dist/lit/components/stack/index.js +103 -0
  135. package/dist/lit/components/switch/index.css +126 -0
  136. package/dist/lit/components/switch/index.d.ts +17 -0
  137. package/dist/lit/components/switch/index.js +116 -0
  138. package/dist/lit/components/table/index.css +85 -0
  139. package/dist/lit/components/table/index.d.ts +25 -0
  140. package/dist/lit/components/table/index.js +139 -0
  141. package/dist/lit/components/tabs/index.css +116 -0
  142. package/dist/lit/components/tabs/index.d.ts +49 -0
  143. package/dist/lit/components/tabs/index.js +320 -0
  144. package/dist/lit/components/text-field/index.css +90 -0
  145. package/dist/lit/components/text-field/index.d.ts +17 -0
  146. package/dist/lit/components/text-field/index.js +101 -0
  147. package/dist/lit/components/textarea/index.css +55 -0
  148. package/dist/lit/components/textarea/index.d.ts +26 -0
  149. package/dist/lit/components/textarea/index.js +124 -0
  150. package/dist/lit/components/tooltip/index.css +37 -0
  151. package/dist/lit/components/tooltip/index.d.ts +31 -0
  152. package/dist/lit/components/tooltip/index.js +196 -0
  153. package/dist/lit/components/validation/index.css +386 -0
  154. package/dist/lit/components/validation/index.d.ts +45 -0
  155. package/dist/lit/components/validation/index.js +318 -0
  156. package/dist/lit/index.d.ts +50 -0
  157. package/dist/lit/index.js +59 -0
  158. package/package.json +81 -0
  159. package/styles/README.md +346 -0
  160. package/styles/_elevation.css +24 -0
  161. package/styles/_fonts.css +6 -0
  162. package/styles/_layout.css +37 -0
  163. package/styles/_primitives.css +154 -0
  164. package/styles/_scroll.css +75 -0
  165. package/styles/_semantic.css +146 -0
  166. package/styles/_space.css +61 -0
  167. package/styles/_type.css +139 -0
  168. package/styles/_xmesh-extensions.css +232 -0
  169. package/styles/index.css +44 -0
  170. package/styles/md3/_color.css +102 -0
  171. package/styles/md3/_elevation.css +26 -0
  172. package/styles/md3/_motion.css +35 -0
  173. package/styles/md3/_shape.css +22 -0
  174. package/styles/md3/_state.css +22 -0
  175. package/styles/md3/_type.css +111 -0
@@ -0,0 +1,105 @@
1
+ /*
2
+ sidebar-item/index.ts — Lit port of components/sidebar-item/index.jsx.
3
+
4
+ <xm-sidebar-item> — chat-list row in the sidebar.
5
+
6
+ Properties:
7
+ title string — row label
8
+ layout "row" | "stacked" (default "row")
9
+ active boolean
10
+ hover boolean — preview-only force state
11
+ showDot boolean — render the leading accent dot in row layout
12
+ collapsed boolean — render the 4px stripe rail (icon-only mode)
13
+
14
+ Click events:
15
+ Listen for native `click` on the element. The component renders a
16
+ role="button" div that fires the standard click event; consumers can
17
+ do `el.addEventListener("click", …)` or `@click` from a parent.
18
+
19
+ Light DOM. Existing components/sidebar-item/index.css owns all visuals.
20
+ */
21
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
22
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
23
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
24
+ 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;
25
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
26
+ };
27
+ import { LitElement, html } from "lit";
28
+ import { customElement, property } from "lit/decorators.js";
29
+ let XmSidebarItem = class XmSidebarItem extends LitElement {
30
+ constructor() {
31
+ super(...arguments);
32
+ this.title = "";
33
+ this.layout = "row";
34
+ this.active = false;
35
+ this.hover = false;
36
+ this.showDot = false;
37
+ this.collapsed = false;
38
+ }
39
+ createRenderRoot() {
40
+ return this;
41
+ }
42
+ connectedCallback() {
43
+ super.connectedCallback();
44
+ // Make the host transparent to flex layout so the inner .sidebar-item
45
+ // is what the parent panel measures — matches the React tree where
46
+ // <SidebarItem> renders the <div class="sidebar-item"> directly.
47
+ if (!this.style.display)
48
+ this.style.display = "contents";
49
+ }
50
+ render() {
51
+ if (this.collapsed) {
52
+ const cls = `sidebar-item sidebar-item--collapsed ${this.active ? "is-active" : ""}`
53
+ .replace(/\s+/g, " ").trim();
54
+ return html `
55
+ <div
56
+ class="${cls}"
57
+ role="button"
58
+ tabindex="0"
59
+ title="${this.title}"
60
+ ></div>
61
+ `;
62
+ }
63
+ const stateClass = [
64
+ this.active && "is-active",
65
+ this.hover && "is-hover",
66
+ this.showDot && "has-dot",
67
+ ].filter(Boolean).join(" ");
68
+ const cls = `sidebar-item sidebar-item--${this.layout} ${stateClass}`
69
+ .replace(/\s+/g, " ").trim();
70
+ if (this.layout === "stacked") {
71
+ return html `
72
+ <div class="${cls}" role="button" tabindex="0" title="${this.title}">
73
+ <span class="sidebar-item__title">${this.title}</span>
74
+ </div>
75
+ `;
76
+ }
77
+ return html `
78
+ <div class="${cls}" role="button" tabindex="0" title="${this.title}">
79
+ <span class="sidebar-item__dot" aria-hidden="${this.showDot ? "false" : "true"}"></span>
80
+ <span class="sidebar-item__title">${this.title}</span>
81
+ </div>
82
+ `;
83
+ }
84
+ };
85
+ __decorate([
86
+ property({ type: String })
87
+ ], XmSidebarItem.prototype, "title", void 0);
88
+ __decorate([
89
+ property({ type: String })
90
+ ], XmSidebarItem.prototype, "layout", void 0);
91
+ __decorate([
92
+ property({ type: Boolean })
93
+ ], XmSidebarItem.prototype, "active", void 0);
94
+ __decorate([
95
+ property({ type: Boolean })
96
+ ], XmSidebarItem.prototype, "hover", void 0);
97
+ __decorate([
98
+ property({ type: Boolean, attribute: "show-dot" })
99
+ ], XmSidebarItem.prototype, "showDot", void 0);
100
+ __decorate([
101
+ property({ type: Boolean })
102
+ ], XmSidebarItem.prototype, "collapsed", void 0);
103
+ XmSidebarItem = __decorate([
104
+ customElement("xm-sidebar-item")
105
+ ], XmSidebarItem);
@@ -0,0 +1,81 @@
1
+ /* ============================================
2
+ Skeleton — gradient-free loading placeholder.
3
+
4
+ The pulse is a calm OPACITY animation on a neutral surface fill — a
5
+ color-mix between two surface-container tiers. There is NO shimmer /
6
+ sweep gradient anywhere (FR-147 / A10): the snackbar scrim is the
7
+ system's only sanctioned gradient. The animation honors
8
+ prefers-reduced-motion.
9
+
10
+ The fill is neutral chrome — no accent, no severity hue (AD-11). It
11
+ sits on the host surface family it's placed in; the surface-container
12
+ tiers read on both the desk and the inverse card stack, in both themes
13
+ (AD-13).
14
+
15
+ BEM block: `skeleton`. Registered in scripts/check-bem.sh STRICT_BLOCKS.
16
+ Elements: __shape (one placeholder), __line (a text line). Modifiers:
17
+ --line / --block / --circle.
18
+ ============================================ */
19
+
20
+ .skeleton {
21
+ display: block;
22
+ width: 100%;
23
+ }
24
+
25
+ /* Line variant stacks its text lines with a consistent gap. */
26
+ .skeleton--line {
27
+ display: flex;
28
+ flex-direction: column;
29
+ gap: var(--s-2);
30
+ }
31
+
32
+ .skeleton__shape {
33
+ display: block;
34
+ /* Neutral fill — a color-mix between two surface-container tiers. This is
35
+ a flat fill, NOT a gradient: there is no shimmer sweep, no linear- /
36
+ radial-gradient. The pulse comes from the opacity animation below. */
37
+ background: color-mix(
38
+ in oklch,
39
+ var(--md-sys-color-surface-container-high) 60%,
40
+ var(--md-sys-color-surface-container-highest)
41
+ );
42
+ border-radius: var(--md-sys-shape-corner-small);
43
+ /* Calm pulse: alternate opacity, slow tempo, standard easing. */
44
+ animation: skeleton-pulse var(--md-sys-motion-duration-extra-long2)
45
+ var(--md-sys-motion-easing-standard) infinite alternate;
46
+ }
47
+
48
+ /* A single text line — height from the body typescale, full width by default
49
+ (the element narrows the last line of a paragraph via inline width). */
50
+ .skeleton__line {
51
+ height: 0.85em;
52
+ width: 100%;
53
+ }
54
+
55
+ /* Block — arbitrary rectangle (card / image placeholder). */
56
+ .skeleton--block .skeleton__shape {
57
+ height: 120px;
58
+ border-radius: var(--md-sys-shape-corner-medium);
59
+ }
60
+
61
+ /* Circle — avatar / icon placeholder. */
62
+ .skeleton--circle .skeleton__shape {
63
+ width: 40px;
64
+ height: 40px;
65
+ border-radius: var(--md-sys-shape-corner-full);
66
+ }
67
+
68
+ @keyframes skeleton-pulse {
69
+ from {
70
+ opacity: 1;
71
+ }
72
+ to {
73
+ opacity: 0.45;
74
+ }
75
+ }
76
+
77
+ @media (prefers-reduced-motion: reduce) {
78
+ .skeleton__shape {
79
+ animation: none;
80
+ }
81
+ }
@@ -0,0 +1,19 @@
1
+ import { LitElement } from "lit";
2
+ import type { TemplateResult } from "lit";
3
+ export type SkeletonVariant = "line" | "block" | "circle";
4
+ export declare class XmSkeleton extends LitElement {
5
+ variant: SkeletonVariant;
6
+ width: string;
7
+ height: string;
8
+ lines: number;
9
+ radius: string;
10
+ render(): TemplateResult;
11
+ private _renderShape;
12
+ private _renderLines;
13
+ private _shapeStyle;
14
+ }
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ "xm-skeleton": XmSkeleton;
18
+ }
19
+ }
@@ -0,0 +1,119 @@
1
+ /*
2
+ skeleton/index.ts — <xm-skeleton>, gradient-free loading placeholder.
3
+
4
+ Shows the structure of content while data loads. Three shapes via `variant`:
5
+ line — a text line (repeatable via `lines` for a paragraph)
6
+ block — a rectangular block (card / image placeholder)
7
+ circle — a circular avatar / icon placeholder
8
+
9
+ The loading PULSE is gradient-free (AC-2, the headline constraint): it is a
10
+ calm opacity animation on a neutral surface fill (a color-mix between two
11
+ surface-container tiers). There is NO shimmer / sweep gradient anywhere — the
12
+ snackbar scrim is the system's only sanctioned gradient. The pulse respects
13
+ `prefers-reduced-motion` (CSS disables the animation).
14
+
15
+ The placeholder is decorative: it carries `aria-hidden="true"`. The HOST that
16
+ owns the loading state carries `aria-busy` — the skeleton does not announce.
17
+
18
+ Authoring:
19
+ <xm-skeleton variant="line" lines="3"></xm-skeleton>
20
+ <xm-skeleton variant="block" width="100%" height="160px"></xm-skeleton>
21
+ <xm-skeleton variant="circle" width="40px"></xm-skeleton>
22
+
23
+ Properties:
24
+ variant "line" | "block" | "circle" (default "line")
25
+ width CSS length for the shape (block/circle/line)
26
+ height CSS length (block); line/circle derive their own height
27
+ lines number of text lines (line variant only; default 1)
28
+ radius CSS length override for corner rounding (block variant)
29
+
30
+ Shadow DOM. Depends only on tokens — no overlay, no primitives (AD-12).
31
+ Reused by xm-data-table loading rows (Epic 6, FR-161): a row of line/block
32
+ placeholders composes from these variants.
33
+ */
34
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
35
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
36
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
37
+ 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;
38
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
39
+ };
40
+ import { LitElement, html } from "lit";
41
+ import { customElement, property } from "lit/decorators.js";
42
+ const SKELETON_CSS = new URL("../skeleton/index.css", import.meta.url).href;
43
+ let XmSkeleton = class XmSkeleton extends LitElement {
44
+ constructor() {
45
+ super(...arguments);
46
+ this.variant = "line";
47
+ this.width = "";
48
+ this.height = "";
49
+ this.lines = 1;
50
+ this.radius = "";
51
+ }
52
+ render() {
53
+ const v = this.variant === "block" || this.variant === "circle"
54
+ ? this.variant
55
+ : "line";
56
+ const cls = `skeleton skeleton--${v}`;
57
+ return html `
58
+ <link rel="stylesheet" href="${SKELETON_CSS}" />
59
+ <style>
60
+ :host { display: block; }
61
+ :host([hidden]) { display: none; }
62
+ </style>
63
+ <div class="${cls}" aria-hidden="true">
64
+ ${v === "line" ? this._renderLines() : this._renderShape()}
65
+ </div>
66
+ `;
67
+ }
68
+ _renderShape() {
69
+ const style = this._shapeStyle();
70
+ return html `<span class="skeleton__shape" style=${style}></span>`;
71
+ }
72
+ _renderLines() {
73
+ const count = Math.max(1, Math.floor(this.lines) || 1);
74
+ const lines = Array.from({ length: count }, (_v, i) => {
75
+ // The last line of a paragraph runs short for a natural ragged edge.
76
+ const isLast = i === count - 1 && count > 1;
77
+ const w = this.width || (isLast ? "62%" : "100%");
78
+ return html `<span
79
+ class="skeleton__shape skeleton__line"
80
+ style="width:${w};"
81
+ ></span>`;
82
+ });
83
+ return html `${lines}`;
84
+ }
85
+ _shapeStyle() {
86
+ const parts = [];
87
+ if (this.width)
88
+ parts.push(`width:${this.width};`);
89
+ if (this.variant === "circle") {
90
+ // A circle is square: height tracks width unless given explicitly.
91
+ parts.push(`height:${this.height || this.width || "40px"};`);
92
+ }
93
+ else if (this.height) {
94
+ parts.push(`height:${this.height};`);
95
+ }
96
+ if (this.radius)
97
+ parts.push(`border-radius:${this.radius};`);
98
+ return parts.join("");
99
+ }
100
+ };
101
+ __decorate([
102
+ property({ type: String })
103
+ ], XmSkeleton.prototype, "variant", void 0);
104
+ __decorate([
105
+ property({ type: String })
106
+ ], XmSkeleton.prototype, "width", void 0);
107
+ __decorate([
108
+ property({ type: String })
109
+ ], XmSkeleton.prototype, "height", void 0);
110
+ __decorate([
111
+ property({ type: Number })
112
+ ], XmSkeleton.prototype, "lines", void 0);
113
+ __decorate([
114
+ property({ type: String })
115
+ ], XmSkeleton.prototype, "radius", void 0);
116
+ XmSkeleton = __decorate([
117
+ customElement("xm-skeleton")
118
+ ], XmSkeleton);
119
+ export { XmSkeleton };
@@ -0,0 +1,171 @@
1
+ /* ============================================
2
+ xm-slider — draggable range slider on XmField (Story 2.8).
3
+
4
+ Extends XmField for chrome but renders its own layout (the bordered text-field
5
+ box is wrong for a slider): a label row (label + optional value), a track row
6
+ (rail + active fill + thumb), and the helper/error row. State machinery
7
+ (disabled / form-association / focus / ARIA) is inherited; this file styles the
8
+ track, fill, thumb, label, and value.
9
+
10
+ Surface & ink (AD-13): the slider rides the inverse-surface card tier — label +
11
+ value are inverse-on-surface ink. The active (filled) portion + the thumb are
12
+ the single coral accent (--md-sys-color-primary). The inactive rail, track
13
+ height, and thumb size are --xm-slider-* extensions (AD-10). Coral = the filled
14
+ value, never severity (AD-11). The error string carries severity via the warn
15
+ icon + copy.
16
+
17
+ Motion (NFR-19): fill/thumb position is layout-driven; the focus ring + hover
18
+ transition short3 standard, no bounce.
19
+
20
+ BEM block: `slider`. Registered in scripts/check-bem.sh STRICT_BLOCKS.
21
+ ============================================ */
22
+
23
+ .slider {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: var(--s-2);
27
+ width: 100%;
28
+ }
29
+
30
+ /* ---------- Label row — field label + optional value ---------- */
31
+ .slider__label-row {
32
+ display: flex;
33
+ align-items: baseline;
34
+ justify-content: space-between;
35
+ gap: var(--s-2);
36
+ }
37
+ .slider__label {
38
+ display: inline-flex;
39
+ align-items: center;
40
+ gap: var(--s-1);
41
+ color: var(--md-sys-color-inverse-on-surface);
42
+ font:
43
+ var(--md-sys-typescale-label-large-weight)
44
+ var(--md-sys-typescale-label-large-size) /
45
+ var(--md-sys-typescale-label-large-line-height)
46
+ var(--md-sys-typescale-label-large-font);
47
+ }
48
+ .slider__label-text {
49
+ letter-spacing: 0;
50
+ }
51
+ .slider__required {
52
+ color: var(--md-sys-color-primary);
53
+ font-weight: 700;
54
+ line-height: 1;
55
+ }
56
+ .slider__value {
57
+ color: var(--md-sys-color-inverse-on-surface);
58
+ font:
59
+ var(--md-sys-typescale-label-medium-weight)
60
+ var(--md-sys-typescale-label-medium-size) /
61
+ var(--md-sys-typescale-label-medium-line-height)
62
+ var(--md-sys-typescale-label-medium-font);
63
+ font-variant-numeric: tabular-nums;
64
+ }
65
+
66
+ /* ---------- Track — rail + active fill + thumb ---------- */
67
+ .slider__track {
68
+ position: relative;
69
+ display: flex;
70
+ align-items: center;
71
+ height: var(--xm-slider-thumb-size);
72
+ /* Inset the interactive box by half a thumb so the thumb (positioned by its
73
+ center at left:fraction) never overflows the field width. The rail/fill and
74
+ the pointer math all share this same inset coordinate space. */
75
+ margin: 0 calc(var(--xm-slider-thumb-size) / 2);
76
+ cursor: pointer;
77
+ touch-action: none;
78
+ }
79
+
80
+ .slider__rail {
81
+ position: absolute;
82
+ left: 0;
83
+ right: 0;
84
+ height: var(--xm-slider-track-height);
85
+ border-radius: var(--md-sys-shape-corner-full);
86
+ background: var(--xm-slider-track-inactive);
87
+ }
88
+
89
+ .slider__fill {
90
+ position: absolute;
91
+ left: 0;
92
+ height: var(--xm-slider-track-height);
93
+ border-radius: var(--md-sys-shape-corner-full);
94
+ background: var(--md-sys-color-primary);
95
+ }
96
+
97
+ .slider__thumb {
98
+ position: absolute;
99
+ top: 50%;
100
+ width: var(--xm-slider-thumb-size);
101
+ height: var(--xm-slider-thumb-size);
102
+ margin-left: calc(var(--xm-slider-thumb-size) / -2);
103
+ transform: translateY(-50%);
104
+ border-radius: var(--md-sys-shape-corner-full);
105
+ background: var(--md-sys-color-primary);
106
+ box-shadow: var(--xm-slider-thumb-shadow);
107
+ outline: none;
108
+ cursor: grab;
109
+ transition: box-shadow var(--md-sys-motion-duration-short3)
110
+ var(--md-sys-motion-easing-standard);
111
+ }
112
+ .slider__thumb:active {
113
+ cursor: grabbing;
114
+ }
115
+
116
+ /* Focus ring — the canonical 3px coral halo on the thumb. */
117
+ .slider__thumb:focus-visible {
118
+ box-shadow:
119
+ var(--xm-slider-thumb-shadow),
120
+ var(--xm-state-focus-ring);
121
+ }
122
+
123
+ /* ---------- Disabled — shared reduced emphasis ---------- */
124
+ .slider--disabled .slider__track {
125
+ cursor: not-allowed;
126
+ }
127
+ .slider--disabled .slider__thumb {
128
+ cursor: not-allowed;
129
+ box-shadow: none;
130
+ }
131
+ .slider--disabled .slider__rail,
132
+ .slider--disabled .slider__fill,
133
+ .slider--disabled .slider__thumb {
134
+ opacity: 0.45;
135
+ }
136
+ .slider--disabled .slider__label,
137
+ .slider--disabled .slider__value {
138
+ color: var(--xm-color-inverse-on-surface-disabled);
139
+ }
140
+
141
+ /* ---------- Helper / error message row ----------
142
+ Severity is the warn icon + copy, not a color (rule 3a). */
143
+ .slider__message {
144
+ display: flex;
145
+ align-items: flex-start;
146
+ gap: var(--s-1);
147
+ min-height: 1em;
148
+ font:
149
+ var(--md-sys-typescale-body-small-weight)
150
+ var(--md-sys-typescale-body-small-size) /
151
+ var(--md-sys-typescale-body-small-line-height)
152
+ var(--md-sys-typescale-body-small-font);
153
+ }
154
+ .slider__message--helper {
155
+ color: var(--xm-color-inverse-on-surface-muted);
156
+ }
157
+ .slider__message--error {
158
+ color: var(--md-sys-color-inverse-on-surface);
159
+ }
160
+ .slider__error-icon {
161
+ display: inline-flex;
162
+ align-items: center;
163
+ flex-shrink: 0;
164
+ margin-top: 1px;
165
+ color: var(--md-sys-color-inverse-on-surface);
166
+ }
167
+ .slider__message-text {
168
+ flex: 1;
169
+ min-width: 0;
170
+ text-wrap: pretty;
171
+ }
@@ -0,0 +1,36 @@
1
+ import type { PropertyValues, TemplateResult } from "lit";
2
+ import { XmField } from "../field/index.js";
3
+ export declare class XmSlider extends XmField {
4
+ min: number;
5
+ max: number;
6
+ step: number;
7
+ /** Show the current numeric value as a label beside the track. */
8
+ showValue: boolean;
9
+ /** Optional unit appended to the displayed value (e.g. "%", "px"). */
10
+ unit: string;
11
+ private _track;
12
+ private _dragging;
13
+ connectedCallback(): void;
14
+ /** Typed live read; the inherited string `value` stays in sync. */
15
+ get valueAsNumber(): number;
16
+ private get _num();
17
+ private get _fraction();
18
+ private _clampSnap;
19
+ private _setValue;
20
+ private _commit;
21
+ private _valueFromClientX;
22
+ private _onPointerDown;
23
+ private _onPointerMove;
24
+ private _onPointerUp;
25
+ private _focusThumb;
26
+ private _onKeydown;
27
+ private _onBlur;
28
+ protected updated(changed: PropertyValues<this>): void;
29
+ private get _valueText();
30
+ render(): TemplateResult;
31
+ }
32
+ declare global {
33
+ interface HTMLElementTagNameMap {
34
+ "xm-slider": XmSlider;
35
+ }
36
+ }